Display spinner on each API call automatically in Blazor

Published on Thursday, 2 January 2020

Update to .NET 5

What is Blazor ?

Blazor is a free and open-source web framework that enables developers to create web apps using C# and HTML.

To know more about what blazor and all related stuff to it visit official documentation site.

If you have already up and running blazor application you are good to go along. if not, visit official documentation to setup and configure blazor on your machine.

Link of official documentation to get started with Blazor
Get started with Blazor

We often want to show some loading or spinner on UI when our application is making some request to the server, so that users will know that there are some operation going on and need to wait till that operation is complete, We can handle this manually on each time in our code when there is an API call we can show some loading bar but There is a better way to do this and ie let it show the spinner automatically when there is ongoing API call and we can do this my adding our own custom HttpMessageHandler and show spinner just before sending request and hide that after getting response from the server.

Steps

  1. Create Spinner Service
  2. Create Spinner Component
  3. Create Custom HttpMessageHandler
  4. Add Spinner Component in MainLayout
  5. Register Services in startup

Step 1 : Create Spinner Service

Spinner Service class exposes two methods and two event, which will work as a communication channel between other Components (MainLayout) and Spinner component

public class SpinnerService
	{
		public event Action OnShow;
		public event Action OnHide;

		public void Show()
		{
			OnShow?.Invoke();
		}

		public void Hide()
		{
			OnHide?.Invoke();
		}
	}

Step 2 : Create Spinner Component

Here in this Spinner component , I have some css to show the Spinner on top of other html elements and for Spinner I'm using a Blazor Library called Faso.Blazor.SpinKit , which we can install from NuGet , It has a different kind of spinner , here I'm using <SpinKitCircle />. to know more about this spineer visit Github Repo of this this NuGet library.

Here our logic is simple when IsVisible will be true it will show the spinner and in the case of false it will hide.

From our Spinner service when OnShow event will be fired, ShowSpinner() method will be called it will make IsVisible true same on OnHide HideSpinner() method will be called and it will make IsVisible false.

@using Faso.Blazor.SpinKit
@inject SpinnerService SpinnerService

<style>
    .spinner-container {
        display: flex;
        flex-direction: column;
        position: fixed;
        z-index: 999;
        top: 50%;
        left: 50%;
    }
</style>
@if (IsVisible)
{
    <div class="spinner-container">
        <SpinKitCircle />
    </div>
}
@code
{
    protected bool IsVisible { get; set; }
    protected override void OnInitialized()
    {
        SpinnerService.OnShow += ShowSpinner;
        SpinnerService.OnHide += HideSpinner;
    }

    public void ShowSpinner()
    {
        IsVisible = true;
        StateHasChanged();
    }

    public void HideSpinner()
    {
        IsVisible = false;
        StateHasChanged();
    }
}

Step 3 : Create Custom HttpMessageHandler

In order to fire OnShow and OnHide event each time our application will make request we need to add our own custom HttpMessageHandler. (i.e. BlazorDisplaySpinnerAutomaticallyHttpMessageHandler)

Here in our custom HttpMessageHandler we are injecting SpinnerService so that we can call Show() and Hide() method from custom HttpMessageHandler that will fire events.

using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace BlazorDisplaySpinnerAutomatically
{
    public class BlazorDisplaySpinnerAutomaticallyHttpMessageHandler : DelegatingHandler
    {       
        private readonly SpinnerService _spinnerService;
        public BlazorDisplaySpinnerAutomaticallyHttpMessageHandler(SpinnerService spinnerService)
        {
            _spinnerService = spinnerService;
        } 
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            _spinnerService.Show();
          //  await Task.Delay(1000);
            var response = await base.SendAsync(request, cancellationToken);
            _spinnerService.Hide();
            return response;            
        }
    }
}

Step 4 : Add Spinner Component in MainLayout

MainLayout is component which will be rendered for each component so we will add our Spinner component on our MainLayout Component.

<Spinner></Spinner>

<div class="sidebar">
    <NavMenu />
</div>

<div class="main">
    <div class="top-row px-4">
        <a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a>
    </div>

    <div class="content px-4">
        @Body
    </div>
</div>

Step 5 : Register Services

Now our final step is to register our services in startup , here we are registering SpinnerService , Our Custom HttpMessageHandler (i.e. BlazorDisplaySpinnerAutomaticallyHttpMessageHandler) and Also we need to register HttpClient and pass our custom HttpMessageHandler as InnerHandler.

 public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("app");

            builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
            builder.Services.AddScoped<SpinnerService>();
            builder.Services.AddScoped<BlazorDisplaySpinnerAutomaticallyHttpMessageHandler>();
            builder.Services.AddScoped(s =>
            {
                var accessTokenHandler = s.GetRequiredService<BlazorDisplaySpinnerAutomaticallyHttpMessageHandler>();
                accessTokenHandler.InnerHandler = new HttpClientHandler();
                var uriHelper = s.GetRequiredService<NavigationManager>();
                return new HttpClient(accessTokenHandler)
                {
                    BaseAddress = new Uri(uriHelper.BaseUri)
                };
            });
            await builder.Build().RunAsync();
        }
    }

Now run the application , you should see a spinner ,when application will make http calls.

We can show that spinner from other components as well when ever we need to show, we just has to inject SpinnerService and call Show() and Hide() method to show and hide spinner respectively.

Refrence Links

  1. Creating a Reusable, JavaScript-Free Blazor Modal
  2. faso/Faso.Blazor.SpinKit

Feel free to comment and suggests changes .

Full source code BlazorDisplaySpinnerAutomatically

Happy Coding!