Live Chat Icon For mobile
Live Chat Icon

Blazor FAQ

Find answers for the most frequently asked questions
Expand All Collapse All

To upload files in Blazor applications, install the NuGet package, BlazorInputFile. This package has the component, InputFile  that isused to upload files.
You also need to include the input file scripts in HTML and add BlazorInputs to the _Imports.razor file.

[_Host.cshtml]

  <script src="_content/BlazorInputFile/inputfile.js"></script>
[index.razor]

@page "/upload"

<h3>Upload</h3>

<InputFile OnChange="HandleFileSelected"  class="btn-primary"/>

@if (file != null)
{
    <p>Name: @file.Name</p>
    <p>Size in bytes: @file.Size</p>
    <p>Last modified date: @file.LastModified.ToShortDateString()</p>
    <p>Content type (not always supplied by the browser): @file.Type</p>
}

@code {
    IFileListEntry file;

    void HandleFileSelected(IFileListEntry[] files)
    {
        file = files.FirstOrDefault();
    }
}

You can handle multiple file uploads by adding multiple attribute to the InputFile component.

@page "/multiupload"

<h3>Multiple File Upload</h3>

<InputFile multiple OnChange="HandleFileSelected"  class="btn-primary"/>

@if (file != null)
{
   <p>Name: @file.Name</p>
   <p>Size in bytes: @file.Size</p>
    <p>Last modified date: @file.LastModified.ToShortDateString()</p>
    <p>Content type (not always supplied by the browser): @file.Type</p>
}

@code {
    IFileListEntry file;

    void HandleFileSelected(IFileListEntry[] files)
    {
        file = files.FirstOrDefault();
    }
}

Please refer to this link here for more information on file uploading in Blazor.

Note: Syncfusion offers feature rich as well as easy to use file upload component. For more information, please check the link.

Permalink

Blazor detects the UI changes in common scenarios like EventCallback (button click, dropdown select, etc.), and refreshes the component. However, there are some situations in an app where a UI refresh needs to be triggered manually to re-render the component. The StateHasChanged method is used to force re-render a component UI.

@using System.Threading;

<h1>@Count</h1>

<button @onclick=@StartCountdown>Start Timer</button>

@functions {
    private int Count { get; set; } = 10;

    void StartCountdown()
    {
        var timer = new Timer(new TimerCallback(_ =>
        {
            if (Count > 0)
            {
                Count--;

                // Note that the following line is necessary because otherwise
                // Blazor would not recognize the state change and not refresh the UI
                InvokeAsync(() =>
                {

                    StateHasChanged();
                });
            }
        }), null, 1000, 1000);
    }
}
Permalink

Blazor application renders UI as a HTML content in client-side (browser). So, based on the width of the viewport in a device you can determine if it is a Desktop or a Mobile device and thus design responsive web pages accordingly.

The meta tag named “viewport” is used to design the webpage responsiveness and this is included in all Blazor applications, _Host.cshtml file in Blazor server-side application and index.html file in Blazor Web Assembly application. CSS styling makes designs responsive in Blazor apps.

For more details, refer to this link.

Permalink

String comparison with case insensitivity can be carried out using the String.Compare method, where the first and second parameters are the strings to be compared and the third parameter is for ignoring case sensitivity (case insensitive comparison).

Refer to the following code.

@page "/"

<h1>Case in-sensitive string comparision</h1>

<br />

<EditForm Model="@_stringCompare">
    String 1:
    <InputText id="string1" @bind-Value="_stringCompare.String1" />
    <br />
    String 2:
    <InputText id="string2" @bind-Value="_stringCompare.String2" />
    <br />
</EditForm>

<br />

<button @onclick="Compare">Compare</button>

<br />
<br />

<p>@Output</p>

<br />

@code {

    private StringCompare _stringCompare = new StringCompare();
    public string Output = "";

    public class StringCompare
    {
        public string String1 { get; set; }
        public string String2 { get; set; }
    }

    public async void Compare()
    {
        int CheckValue = String.Compare(_stringCompare.String1, _stringCompare.String2, true);
        Output = "Entered Strings are " + (CheckValue == 0 ? "" : "not ") + "Similar";
        await Task.Run(() => TimeOutMethod());
        Output = "";
        await Task.CompletedTask; 
    }

    void TimeOutMethod() => Task.Delay(3000).Wait();
}

You can download the reference sample here.

Permalink

The property value in the select control can be used to set the default value in select control.

@page "/dropdown"

<select class="form-control" value="@defaultValue " @onchange="@OnSelect" style="width:150px">
       @foreach (var template in templates)
        {
     <option value=@template>@template</option>
         }
 </select>

<h5>@selectedString</h5>

@code {
List<string> templates = new List<string>() { "America", "China", "India", "Russia", "England" };
string selectedString = "";
string defaultValue = "India";
void OnSelect(ChangeEventArgs e)
{
       selectedString = "Selected Country is: " + e.Value.ToString();
}
    }
Permalink

To add Bing Maps to a Blazor application follow the steps.

  • Include the Bing Maps Web API scripts in the index.html/_Host.cshtml, This is used to retrieve the Bing Maps-related information by sending a request to the Bing Maps server and loading the same to the Blazor application.
  • Initialize maps in a Blazor application by using a JavaScript interop in the razor file [index.razor].

Please find the sample below.

[script.js]
function loadBingMap() {
      var map = new Microsoft.Maps.Map(document.getElementById('map'), {});
      var pushpin = new Microsoft.Maps.Pushpin(map.getCenter(), null);
      map.entities.push(pushpin);
      return "";
}
[index.html/_Host.cshtml]

<script src='https://www.bing.com/api/maps/mapcontrol?callback=GetMap&key=api_key' type='text/javascript'></script>
@page "/bingmaps"
@inject IJSRuntime JSRuntime

<h1>Display Bing Map</h1>
<div id="map" style="height:500px;width:100%;"> </div>

@code {
    
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
if (firstRender)
{
       await JSRuntime.InvokeVoidAsync("loadBingMap", null); 
  }
     }

}

Permalink

To use jQuery UI components in a Blazor application follow the steps:

  • Reference the source scripts for jQuery and its UI components.
  • Create the elements required for rendering jQuery UI components in the razor page [index.razor].
  • Initialize the jQuery components in the OnAfterRender lifecycle method in your Blazor application by using the JavaScript Interop’s InvokeVoidAsync method.

Refer to the following code sample.

[_Host.cshtml]

….
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <script src="~/script.js"></script>
….

[index.razor]

@page "/"
@inject IJSRuntime jsRuntime

<h1>jQuery UI Components in Blazor</h1>

<br />

<h2>jQuery Accordion Component</h2>

<br />

<div id="accordion">
    <h3>ASP.NET</h3>
    <div>
        <p>
            Microsoft ASP.NET is a set of technologies in the Microsoft .NET Framework for building Web applications and XML Web services.
            ASP.NET pages execute on the server and generate markup such as HTML, WML, or XML that is sent to a desktop or mobile browser.
            ASP.NET pages use a compiled,event-driven programming model that improves performance and enables the separation of application logic and user interface.
        </p>
    </div>
    <h3>ASP.NET MVC</h3>
    <div>
        <p>
            The Model-View-Controller (MVC) architectural pattern separates an application into three main components: the model, the view, and the controller.
            The ASP.NET MVC framework provides an alternative to the ASP.NET Web Forms pattern for creating Web applications.
            The ASP.NET MVC framework is a lightweight, highly testable presentation framework that (as with Web Forms-based applications) is integrated with existing ASP.NET features, such as master pages and membership-based authentication.
        </p>
    </div>
    <h3>JavaScript</h3>
    <div>
        <p>
            JavaScript (JS) is an interpreted computer programming language.
            It was originally implemented as part of web browsers so that client-side scripts could interact with the user, control the browser, communicate asynchronously, and alter the document content that was displayed.
            More recently, however, it has become common in both game development and the creation of desktop applications.
        </p>
    </div>
</div>

<br />

<div class="jquery-btn">
    <button>Click Me</button>
</div>

<br />

<p>Clicked: <span class="click-count">0</span></p>

<br />

@code {
    protected override async void OnAfterRenderAsync(bool firstRender)
    {
        await jsRuntime.InvokeVoidAsync("renderjQueryComponents");
        await base.OnAfterRenderAsync(firstRender);
    }
}

[script.js]

var clickCount = 0;

function renderjQueryComponents() {
    $("#accordion").accordion();
    $(".jquery-btn button").button();
    $(".jquery-btn button").click(function () {
        console.log('Clicked');
        $('.click-count')[0].innerText = ++clickCount;
    });
}

You can download the reference sample here.

Permalink

First to access browser seesionStorage in Blazor apps, write a custom code or use a third party package. The accessed data can be stored in the localStorage and sessionStorage.  The localStorage is scoped to the user’s browser. If the user reloads the page or closes and reopens the browser, the state persists. Session storage is similar to the local storage but the data in the session storage will be cleared after the session.

Use the Blazored.SessionStorage package to store the session data in Blazor. For this install the package and add the service to the application.

[startup.cs]
using Blazored.SessionStorage;

public void ConfigureServices(IServiceCollection services)
{
         services.AddBlazoredSessionStorage();
}
[index.razor]
@page "/"
@inject Blazored.SessionStorage.ISessionStorageService sessionStorage

<h2>@Name</h2>
<button @onclick="Clear">Clear Session</button>
@code {
    public string Name;
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await sessionStorage.SetItemAsync("ID", "20019");
        await sessionStorage.SetItemAsync("Name", "John Smith");
        Name = "ID: " + await sessionStorage.GetItemAsync<string>("ID") + "Name : " + await sessionStorage.GetItemAsync<string>("Name");
    }
   public async void Clear()
   { 
    //this will clear the session data 
     await sessionStorage.ClearAsync();
    }
}

Reference link: https://github.com/blazored/SessionStorage

Permalink

To access browser localStorage in Blazor apps, write a custom code or use a third party package. The difference between localStorage and sessionStorage  is: The localStorage is scoped to the user’s browser. If the user reloads the page or closes and reopens the browser, the state persists. Session storage is similar to local storage but the data in the session storage will be cleared after the session.

The Blazored.LocalStorage package can be used to access the browser’s local storage in Blazor. For this you need to install the package and add the service to the application.

[startup.cs]

public void ConfigureServices(IServiceCollection services)
{
         services.AddBlazoredLocalStorage();
}
[index.razor]
@page "/"
@inject Blazored.LocalStorage.ILocalStorageService localStorage

<h2>@Name</h2>
<button @onclick="Clear">Clear LocalStorage</button>
@code {
    public string Name;
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await localStorage.SetItemAsync("ID", "20019");
        await localStorage.SetItemAsync("Name", "John Smith");
        Name = "ID: " + await localStorage.GetItemAsync<string>("ID") + "Name : " + await localStorage.GetItemAsync<string>("Name");
    }
    public async void Clear()
   {
    //this will clear the local storage 
     await localStorage.ClearAsync();
    }

}

To access the local storage using the OnInitialized method, disable the ServerPrerender in _Host.cshtml.

Reference link: https://chrissainty.com/blazored-local-storage-v0-3-0-released/

Permalink

In Blazor, there are three ways to use different CSS files in different pages .

1. Use inline <style></style> tag to define the custom styling for the page.

2. Include a new CSS file in the page by using a JavaScript interop in the OnInitialized method.

[script.js]

function includeCss() {
     var element = document.createElement("link");
     element.setAttribute("rel", "stylesheet");
     element.setAttribute("type", "text/css");
     element.setAttribute("href", "css/external.css");//location of the css that we want     include for the page
     document.getElementsByTagName("head")[0].appendChild(element);
}
[index.razor]

@page “/”

<h1>Blazor Application</h1>

@code{
    protected override async void OnInitialized()
    {
        await JSRuntime.InvokeAsync<object>("includeCss");
     }
    }

3. Usedirect links of the CSS file via the <link> HTML element with its local or online reference in the href attribute.

<link href="StyleSheet.css" rel="stylesheet" />
Permalink

To add Google Maps to a Blazor application, use the Google Maps API script. To initialize Google Maps in Blazor we need to use a JavaScript interop.

Add the following scripts to ~/Pages/_Host.cshtml for Server Blazor app or ~/wwwroot/index.html for Blazor WebAssembly app.

[_Host.cshtml/index.html]

<head>
    <script src="~/script.js"></script>
    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=&callback=initMap"></script>
</head>
[script.js]

function initialize() {
var latlng = new google.maps.LatLng(40.716948, -74.003563);
var options = {
     zoom: 14, center: latlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById ("map"), options);
}
[index.razor]

@page "/"

@inject IJSRuntime JSRuntime

<h1>Display Google Map</h1>
<div id="map" style="height:500px;width:100%;">
</div>

@code{
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JSRuntime.InvokeVoidAsync("initialize", null); 
        }
    }
}

In the above example, Google Maps is initialized in the OnAfterRenderAsync life cycle method. By invoking it using a JavaScript interop, this will initialize Google Map API when the page is rendered.

You can download the reference sample here.

Permalink
  • Razor is a templating engine that combines C# with HTML to build dynamic web content.
  • Blazor is a component-based, single-page app framework for building client-side web apps using .NET that works well with all modern browsers via WebAssembly for client-side Blazor. Server-side Blazor ASP.NET Core app runs on server and makes use of SignalR connection to communicate with the client (browser). It works with all modern browsers. In other words, Blazor is a hosting model for Razor components.

For detailed information, refer to these links:

Permalink

Blazor is a component-based, single-page web app framework build using .NET.  It works well with all modern browsers via WebAssembly for client-side Blazor. Server-side Blazor ASP.NET Core app runs on server and makes use of SignalR connection to communicate with the client (browser).

Permalink

We can perform asynchronous calls in a Blazor application using async and await keywords for calling any asynchronous Task or performing any operation.

Refer to the following code snippet.

[Index.razor]

@page "/"

<button @onclick="Compare">Compare</button>
<br />
<p>@content</p>

@code {

    public string content = "Some Text";

    public async void  Compare()
    {
        await Task.Run(() => TimeOutMethod());
        content = "";
        await Task.CompletedTask;
        
    }

    void TimeOutMethod() => Task.Delay(3000).Wait();

}
Permalink

You can change the default icon provider for Blazor by importing the required icons in the site.css (\wwwroot\css\site.css). The imported icons can be used throughout the application. In the sample, I’ve imported the Material theme icons and used them.

[site.css]

@import url('https://fonts.googleapis.com/icon?family=Material+Icons');
[~/Shared/NavMenu.razor]

<li class="nav-item px-3">
     <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
          <i class="material-icons"> accessibility </i>Home
     </NavLink>
</li>
<li class="nav-item px-3">
      <NavLink class="nav-link" href="counter">
           <i class="material-icons">autorenew</i> Counter
      </NavLink>
 </li>
<li class="nav-item px-3">
      <NavLink class="nav-link" href="fetchdata">Fetch data
      </NavLink>
</li>

In the sample, we have changed the default icons to the Material icons for the home page and counter.

Permalink

You can remove the About section from a Blazor application in the MainLayout.razor page.
Remove the following code from the ~/Shared/MainLayout.razor page

<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
Permalink

Currently there is no direct Canvas support in WebAssembly. In order to draw using Canvas, you can use the third-party, free Blazor.Extensions.Canvas library. Add Blazor.Extensions.Canvas NuGet to your project and add the following code snippet to draw a rectangle. It draws shapes in Blazor with the reference that is created for the Canvas element in the Razor page.

[index.html/_host.cshtml]
<head>

 <script src="_content/Blazor.Extensions.Canvas/blazor.extensions.canvas.js"></script>

</head>
[index.razor]

@page "/"
@using Blazor.Extensions; 
@using Blazor.Extensions.Canvas
@using Blazor.Extensions.Canvas.Canvas2D;

<BECanvas Width="300" Height="400" @ref="_canvasReference"></BECanvas>

@code {
    private Canvas2DContext _context;

    protected BECanvasComponent _canvasReference;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        this._context = await this._canvasReference.CreateCanvas2DAsync();
        await this._context.SetFillStyleAsync("red");

        await this._context.FillRectAsync(10, 100, 100, 100);

        await this._context.SetFontAsync("38px Calibri");
        await this._context.StrokeTextAsync("Hello Blazor!!!", 5, 100);
 }
}
Permalink

You can use a third party API, such as Ipify, to get the IP address of the current request in Blazor. The script api.ipify will return the IP address in JSON format. But this is a workaround. As of now, there is no way to achieve this. In the following code snippet, the IP address will be retrieved from the Ipify API through a JS interop call to the Blazor server.

[_Host.cshtml/index.html]

<script>
function GetAddress() {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = "https://api.ipify.org?format=jsonp&callback=DisplayIP";
    document.getElementsByTagName("head")[0].appendChild(script);
};
function DisplayIP(response) {
    document.getElementById("text").innerHTML = "Your IP Address is " + response.ip;
}
</script>
[index.razor]

@page "/"
@inject IJSRuntime jsRuntime

<button @onclick="GetIp">Get IP!!!</button>
<textarea id="text" style="width:50%;height:40px;" />

@code{
          public async Task GetIp()
          {
                 await jsRuntime.InvokeAsync<object>("GetAddress");
          } 
}
Permalink

We can bind properties to a list by binding every value in the list to each list element using a for loop. Then, if the property gets updated in the list, the HTML DOM will update the concerned item of the list element.

Refer to the following code snippet for further details.

<h1>Bind List</h1>

<button class="btn btn-primary" @onclick="Generate">Generate and Bind to List</button>

@if (list != null)
{
    @foreach (var item in list)
    {
        <li>@item</li>
    }
}

@code {
    List<int> list;
    const int cMaxNumbers = 10;

    protected void Generate()
    {
        list = new List<int>(cMaxNumbers);
        for (int i = 0; i < cMaxNumbers; i++)
        {
            list.Add(i);
        }
    }
}

You can download the reference sample here

Permalink

Blazor will check for an HTML ID on initializing the HTML element. If such an ID does not exist on the page, then it will use the default handler to display messages. To display custom messages  on connection loss, we can define a div element with the ID components-reconnect-modal in the body of _Host.cshtml to manipulate the overlay that shows up in the case of a connection loss. If this element exists, this element’s class will be :

components-reconnect-show: A lost connection. The client is attempting to reconnect. Show the modal. Then, you can apply your custom styling to the screen overlay with CSS. If you want to remove them all, you can just choose not to display them at all.

components-reconnect-hide: An active connection is re-established to the server. Hide the modal.

components-reconnect-failed: Reconnection failed, probably due to a network failure. To attempt reconnection, call window.Blazor.reconnect().

components-reconnect-rejected: Reconnection rejected. The server was reached but refused the connection, and the user’s state on the server is lost. To reload the app, call location.reload().

Refer to this link for more details: https://docs.microsoft.com/en-us/aspnet/core/blazor/hosting-model-configuration?view=aspnetcore-3.1#reflect-the-connection-state-in-the-ui

[_Host.cshmtl]

<body>
……

<div id="components-reconnect-modal" class="my-reconnect-modal components-reconnect-hide">
<div class="show">
    <p>
        // Message when attempting to connect to server
    </p>
</div>
<div class="failed">
    <p>
        // Message when failing to connect
    </p>
</div>
<div class="rejected">
    <p>
        // Message when refused
    </p>
</div>
</div>

……
<app>
    @(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
</app>

</body>
[site.css]

    .my-reconnect-modal > div {
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        z-index: 1000;
        overflow: hidden;
        background-color: #fff;
        opacity: 0.8;
        text-align: center;
        font-weight: bold;
    }

    .components-reconnect-hide > div {
        display: none;
    }

    .components-reconnect-show > div {
        display: none;
    }

    .components-reconnect-show > .show {
        display: block;
    }

    .components-reconnect-failed > div {
        display: none;
    }

    .components-reconnect-failed > .failed {
        display: block;
    }

    .components-reconnect-refused > div {
        display: none;
    }

    .components-reconnect-refused > .refused {
        display: block;
    }

You can download the reference sample here

Permalink

To set the focus to a HTML element in Blazor, use the JavaScript interop to pass the HTML element and then use focus JavaScript method.

[script.js]

window.SetFocusToElement = (element) => {
         element.focus();
};
[index.razor]

@inject IJSRuntime jsRuntime

<div class="jumbotron" tabindex="0"  @ref="myDiv">
</div>

@code {
    string KeyPressed = "";
    protected ElementReference myDiv;  // set the @ref for attribute

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await jsRuntime.InvokeVoidAsync("SetFocusToElement", myDiv);
        }
    }
}
Permalink

While making an API call, create and run an asynchronous task with the Run method to notify the wait using a spinner. The completion of the task can be notified using the  CompletedTask property.

[index.razor]

@page "/"

<style>
    .loader {
        border: 5px solid #f3f3f3;
        border-radius: 50%;
        border-top: 5px solid #f58205;
        width: 30px;
        height: 30px;
        -webkit-animation: spin 2s linear infinite; /* Safari */
        animation: spin 2s linear infinite;
    }
    /* Safari */
    @@-webkit-keyframes spin {
        0% {
            -webkit-transform: rotate(0deg);
        }
        100% {
            -webkit-transform: rotate(360deg);
        }
    }
    @@keyframes spin {
        0% {
            transform: rotate(0deg);
        }
        100% {
            transform: rotate(360deg);
        }
    }
</style>

<h1>Counter</h1>

<p>
    Current count: <div class="@(spin ? "loader" : "")"> @(spin?"":currentCount.ToString()) </div>
</p>

<button class="btn btn-primary" @onclick="@IncrementCount"> Click me </button>
<button class="btn btn-dark" @onclick="@AsyncCallBack"> API Call Back </button>

@code {
    int currentCount = 0;
    bool spin = false;
    void IncrementCount()
    {
        currentCount++;
    }

    async Task AsyncCallBack()
    {
        spin = true;
        await Task.Run(() => APICallBack());  //<==check this!!!
        currentCount++;
        spin = false;
        await Task.CompletedTask;
    }

    void APICallBack() => Task.Delay(1500).Wait();
}

Output:

Permalink

The lifecycle methods OnAfterRenderAsync and OnAfterRender are called only when a component has finished rendering. The element and component references are populated at this point. By using these methods, the user can activate third-party JavaScript libraries that operate based on the DOM elements.

Permalink

Blazor notifies the UI changes automatically whenever the bound property is changed in a button click, input text, dropdown, etc.Blazor triggers the StateHasChanged() method to notify the change. However, there are some exceptional cases where the user has to manually call the StateHasChanged() method to notify that the UI has been updated.

By calling the StateHasChanged(), Blazor can manually be notified when to rerender its UI. This method will tell Blazor when to refresh the UI.

@using System.Threading;

<h1>@Count</h1>

<button @onclick=@StartCountdown>Start Timer</button>

@functions {
    private int Count { get; set; } = 10;

    void StartCountdown()
    {
        var timer = new Timer(new TimerCallback(_ =>
        {
            if (Count > 0)
            {
                Count--;

                // Note that the following line is necessary because otherwise
                // Blazor would not recognize the state change and refresh the UI
                InvokeAsync(() =>
                {
                    StateHasChanged();
                });
            }
        }), null, 1000, 1000);
    }
}

In the above example, when the button is clicked, the UI will refresh for every count down of the timer since StateHasChanged method has been called to refresh the UI.

Permalink

You can delay a task in Blazor by using the Task.Delay() method where the time set for the task to be delayed before proceeding to the next.

<h3>Timer: @Timer</h3>

@code {
    [Parameter] 
    public int Timer { get; set; } = 5;

    public async void StartTimerAsync()
    {
        while (Timer > 0)
        {
            Timer--;
            StateHasChanged();
            await Task.Delay(1000);
        }
    }

    protected override void OnInitialized()
        => StartAsync();
}
Permalink

When StateHasChanged is called, it runs change detection on the current component and its descendants. Blazor is clever enough to rerender the components that have changes.

<h3>StateHasChanged</h3>

<button class="btn btn-primary" @onclick="Generate">Generate List</button>
<button class="btn btn-primary" @onclick="ChangeOneRow">Change State</button>

@if (list != null)
{
       @foreach (var item in list)
       {
               <li>@item</li>
       }
}

@code {
    List<int> list;
    const int cMaxNumbers = 10;

    protected void Generate()
    {
        list = new List<int>(cMaxNumbers);
        for (int i = 0; i < cMaxNumbers; i++)
        {
            list.Add(i);
        }
    }

    protected void ChangeOneRow()
    {
        list[0] = 123456;
        StateHasChanged();
    }
}

In the above example, only the first list will be re-rendered.

Permalink

The StateHasChanged method is called whenever a bound property is changed or a UI event triggered for an instance. This notifies the Blazor that the component should rerender it.

For example, when a button is clicked in the index page, the index component rerenders (no need to call StateHasChanged) because the button’s parent is an index; but when it has a child component it has be notified to render as the parent has changed.

Permalink

Blazor provides both synchronous and asynchronous initialization lifecycle methods to perform additional operations on components during initialization and rendering. Initialization methods are:

  • OnInitialized:  Override this method in components for synchronous operations.
  • OnInitializedAsync:   Override this method in components for asynchronous operations.

OnInitialized and OnInitializedAsync are executed when the component is initialized after having received its initial parameters from its parent component in the render tree.

Use OnInitializedAsync when the component performs an asynchronous operation and the changes should refresh the component when the operation is completed. Refer to this link for more details.

Permalink

You can call the preventDefault action in onclick event of an anchor tag. Refer to the following code sample to prevent opening a link when the link is clicked.

<a href="https://www.syncfusion.com/" target="_blank" @onclick:preventDefault>Syncfusion</a>

This feature was made available from .NET Core 3.1 Preview 2 for Blazor.

You can also perform custom action for onclick in the anchor tag by defining the same onclick event and mapping it to custom action.

<a href="https://www.syncfusion.com/" target="_blank" @onclick:preventDefault  @onclick="@OnClick">Syncfusion</a>
@code {
         public void OnClick(){
              //triggers on click
         }
}
Permalink

State in Blazor:

In Blazor, the user’s state is held in the server’s memory in a circuit. State Management refers to the persisting state of an application even after the connection is lost or disconnected.  The state held for a user’s circuit may be any of the following,

  • UI related data- component instances, rendered output
  • Property/field values of the component instances
  • Dependency injection service instance data

Need for State Management:

In Blazor, the application is connected through a circuit to the  server, which holds the user’s state and this can be lost or disconnected due to multiple reasons. Some of the reasons are as follows,

  • Large number of users accessing the server and increasing the memory used causing the pressure to disconnect the circuit.
  • Users reloading the application/webpage leading to circuit disconnection/loss.

Due to the above, user’s state may be lost and can also cause loss of crucial data gathered in the application such as,

  • Multistep webform
  • Shopping cart

When data is lost after completing processes with multiple steps or creating a shopping list, it results in unnecessary time consumption.  So, in Blazor, the data is stored in the local cache and state persists even when the circuit gets disconnected.

Persisting the State/State Management:

The three locations for persisting state in a Blazor application are as follows,

  • Server-side (Database)
  • Client-side (Browser)
  • URL

Server-side (Database):

To store data/state permanently or any data that spans multiple users or devices, the server-side database should be used.

Client-side (Browser):

Most suited when the user is actively creating transient data, that can be stored in the browsers,  localStorage and sessionStorage.

URL:

This is best suited when the data/state needs to persist when navigating from one page of the application to another.

For more information on state management, refer here.

Permalink

JSON (JavaScript Object Notation) is a lightweight data-interchange format and a text format that is completely language independent. In Blazor, JsonSerializer class helps serialize and deserialize JSON. It is present in the namespace System.Text.Json.

[index.razor]
@page "/"
@using System.Text.Json

<button @onclick="@SerializeDeserializeMethod">Serialize & Deserialize</button>

@code {
    public class User
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
    }

    User user = new User() {ID = 1, Name = "Manas", Address = "India"};

    void SerializeDeserializeMethod()
    {
        //for serialization
        string serializedString = System.Text.Json.JsonSerializer.Serialize(User1);
        //for deserialization
        User userCopy = System.Text.Json.JsonSerializer.Deserialize<User>(serializedString);
    }
}

In the sample using JsonSerialize.Serialize(object), the object user of class user is serialized and stored as a string, then using JsonSerialize.Deserialize<ClassName>(JsonObject) the string serializedString is deserialized with respect to class user as userCopy.

Permalink

Only server-side Blazor is supported by Microsoft’s Internet Explorer IE 11 when additional polyfills are used. Client-side Blazor is not supported by Internet Explorer due to incompatibility of WebAssembly. You need to add the following polyfills in the _Host.cshtml page to support Internet Explorer.

[_Host.cshtml]

//polyfills to be added for Internet Explorer

<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.6.5/core.min.js"></script>

<script src="https://polyfill.io/v3/polyfill.min.js?features=fetch"></script>
Permalink

To install Blazor project templates, update the .NET Core SDK to the latest version. Blazor server-side template is available by default when you create a new Blazor project in Visual Studio. To get the Blazor WebAssembly project template,  install them via the following command line.

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.2.0-preview1.20073.1

Check this link for more information.

Permalink

Blazor has two hosting models, client-side and server-side. Blazor relies on WebAssembly (WASM) for running the Blazor application on the client-side (from browser end itself). The .NET runtime is downloaded with the app along with the app assembly and any required dependencies, then the application is executed directly from the browser UI thread.

Permalink

You can develop a native mobile app in Blazor using Experimental Mobile Blazor Bindings. This allows developers to develop mobile applications in C# and .NET for iOS and Android. It uses Razor syntax to define UI components and the underlying UI components are based on Xamarin.Forms native UI Components. Currently, it is in an experimental mode. 
Check this link to understand the concept: Mobile Blazor Bindings

Permalink

Blazor server-side supports almost all modern browsers out of the box except Microsoft’s Internet Explorer (IE 11), which needs Polyfills to be supported.

[_Host.cshtml]

//polyfills to be added for IE

<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.6.5/core.min.js"></script>

<script src="https://polyfill.io/v3/polyfill.min.js?features=fetch"></script>

Blazor WebAssembly (client-side) supports all the modern browsers except the Internet Explorer.
Check this link for more information.

Permalink

Blazor Server

In server code, configure SignalR in the Startup.cs class file as follows.

public void ConfigureServices(IServiceCollection services)
{
    ... ... ... ...
    services.AddSignalR();
    ... ... ... ...

}


public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ... ... ... ...
    app.UseSignalR(routes => routes.MapHub<Blazor.NetCore.Server.SignalRHub.SignalRHub>("/signalRHub"));
    ... ... ... ...
}

And then create a SignalR hub class as follows.

    public class SignalRHub : Hub
    {
        public override Task OnConnectedAsync()
        {
            Clients.All.SendAsync("ReceiveMessage", "system", $"{Context.ConnectionId} joined the conversation");
            return base.OnConnectedAsync();
        }
        public void SendMessage(string name, string message)
        {
            Clients.All.SendAsync("ReceiveMessage", name, message);
        }

        public override Task OnDisconnectedAsync(System.Exception exception)
        {
            Clients.All.SendAsync("ReceiveMessage", "system", $"{Context.ConnectionId} left the conversation");
            return base.OnDisconnectedAsync(exception);
        }
    }

Blazor client

Create a Blazor app and add the package Blazor.Extensions.SignalR to the client. Then write the code to connect the Hub and event handler as follows.

@page "/signalr"
@using Blazor.Extensions
<div class="container">
    <input type="text" id="user" class="form-control" @bind="@userName" placeholder="User Name" /><br />
    <input type="text" id="message" class="form-control" @bind="@Message" placeholder="Message" /> <br />
    <input type="button" id="sendMessage" value="Send" class="btn btn-primary" @onclick="@SendMessage" />
    <ul id="discussion">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
</div>

@code {
    HubConnection connection;
    string userName = "";
    string Message = "";
    IList<string> messages = new List<string>();

    protected override async Task OnInitializedAsync()
    {
        connection = new HubConnectionBuilder().WithUrl("/signalRHub").Build();
        connection.On<string, string>("receiveMessage", this.ReceiveMessage);
        await connection.StartAsync();
    }

    Task ReceiveMessage(string name, string message)
    {
        messages.Add(name + " : " + message);
        StateHasChanged();
        return Task.CompletedTask;
    }

    async Task SendMessage()
    {
        await connection.InvokeAsync("SendMessage", userName, Message);
        Message = "";
    }
}
  1. OnInitializedAsync method, connect to the Web API.
  2. ReceiveMessage method, used in the SignalRHub class.
  3. ReceiveMessage method, concatenate the name and message parameters, and append them to a list.

The StateHasChanged method will update the bindings in the HTML. The SendMessage method will invoke the Send method in the hub with name and message parameters.

Reference link: https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr-blazor-webassembly?view=aspnetcore-3.1&tabs=visual-studio#add-the-signalr-client-library

Permalink

You have to use JS Interop to create a cookie in Blazor.

[Razor Page]

@page "/"
@inject IJSRuntime JSRuntime

@code {

    private async void CreateCookie(string name, string value, int days)
       {
            var test = await JSRuntime.InvokeAsync<string>("methods.CreateCookie", name, value, days);
       }
}

[Script file]

window.methods = {
    CreateCookie: function (name, value, days) {
     var expires;
     if (days) {
        var date = new Date();
         date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
          expires = "; expires=" + date.toGMTString();
     }
      else {
         expires = "";
     }
      document.cookie = name + "=" + value + expires + "; path=/";
   }    
}

Refer to to How do I create a cookie client-side using Blazor for more information.

Permalink

The NotFound template section in the App.razor can be used for handling 404 pages. The router shows this content if it hits a route that is not available, which is a 404 page.

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="@typeof(MainLayout)">
            <p>Handled 404 page</p>
        </LayoutView>
    </NotFound>
</Router>

Create a component Page/Error.razor to display the 404 content. For more information, read about Blazor routing.

Permalink

Auto rebuild for Visual Studio is now available for Blazor Hosted Projects. Run the project with Ctrl + F5 (without the debugger) instead of F5 and on IIS express. Once .cs and .razor files are changed and saved across the solution, they are automatically rebuilt and the app restarted so that the changes can be seen by simply refreshing the browser.

Reference Link: https://devblogs.microsoft.com/aspnet/blazor-webassembly-3-2-0-preview-3-release-now-available/

Permalink

You can check whether a type of WebAssembly is an object in global scope, but the global scope is not a feasible one across different JavaScript environments, such as a main browser thread, worker, Node.js.

The more feasible solution is as follows.

 const supported = (() => {
      try {
 if (typeof WebAssembly === "object"
             && typeof WebAssembly.instantiate === "function") {
             const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));
             if (module instanceof WebAssembly.Module)
                 return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
         }
     } catch (e) {
     }
     return false;
 })();
  
 console.log(supported ? "WebAssembly is supported" : "WebAssembly is not supported");   

Refer to this StackOverflow link for more information.

Permalink

Quoting Microsoft, “using .NET for client-side web development offers the following advantages:

  • Write code in C# instead of JavaScript.
  • Leverage the existing .NET ecosystem of .NET libraries.
  • Share app logic across the server and client.
  • Benefit from .NET’s performance, reliability, and security.
  • Stay productive with Visual Studio on Windows, Linux, and macOS.
  • Build on a common set of languages, frameworks, and tools that are stable, feature-rich, and easy to use.”

Refer to this Blazor link for more information.

Permalink

Share with

Share on twitter
Share on facebook
Share on linkedin

Couldn't find the FAQs you're looking for?

Please submit your question and answer.