Sure, you could write all those Blazor HTTP calls yourself...

July 15, 2021 · 4 minute read · Tags: blazor

If you’re building a Blazor WASM application you’re almost certainly going to wind up making calls to an API.

The typical way to do this is to use HttpClient:

@using System.Net.Http
@using System.Net.Http.Json
@using System.Threading.Tasks
@inject HttpClient Http

@code {

    private Customer[] customers;
    
    protected override async Task OnInitializedAsync() {
        customers = await Http.GetFromJsonAsync<Customer[]>("api/Customer");
    }

}

This works well, but it does carry a few limitations.

Firstly, your Blazor components are suddenly very tied to that "api/Customer" magic string for the URL of the API endpoint.

If you find yourself making similar calls from more than one component you’re probably going to end up referencing the same endpoint multiple times in different places, meaning any changes to the URL and you’ll be updating multiple components.

Secondly, the API isn’t very discoverable for you or any other developer working on the project.

To consume the API you have to know:

  • The URL of the endpoint
  • The type of the response
  • Potentially the shape (or type) of any data needed for the request

I recently had the chance to work on a new Blazor project and found myself facing these problems, so I had a look for an alternative approach.

Refit can take care of the boilerplate code for you

With Refit you can create a strongly typed interface for your API which moves all this knowledge about URLs, request and response types into one place.

Assuming you already have an API up and running as per our example earlier, you can create a Refit API client like this:

using Refit;

public interface CustomerApi {

    [Get("/Customer")]
    Task<Customer[]> List();

}

You’ll also need a little bit of configuration in your Blazor’s program.cs file.

private static async Task Run(WebAssemblyHostBuilder builder, string[] args)
{
    var apiUrl = "http://localhost:5001/api";    

    builder.Services.AddRefitClient<CustomerApi>()
        .ConfigureHttpClient(c => { c.BaseAddress = new Uri(apiUrl); });
    
    // other code...
}

Now you can happily go ahead and invoke the Api from your Blazor components.

@inject CustomerApi CustomerApi

@code {

    private Customer[] customers;
    
    protected override async Task OnInitializedAsync() {
        customers = await CustomerApi.List();
    }

}

This takes a lot of the guesswork out of consuming your API.

Once this Refit API is in place you can make use of it to call your API without constantly trying to remember (and/or find out) which URL, request or response type to use.

Unleash Blazor's Potential

Blazor promises to make it much easier (and faster) to build modern, responsive web applications, using the tools you already know and understand.

Subscribe to my Practical ASP.NET Blazor newsletter and get instant access to the vault.

In there you'll find step-by-step tutorials, source code and videos to help you get up and running using Blazor's component model.

I respect your email privacy. Unsubscribe with one click.

    Naturally it works for HTTP POST requests as well:

    using Refit;
    
    public interface CustomerApi {
    
        [Get("/Customer")]
        Task<Customer[]> List();
    
        [Post("/Customer")]
        Task Create(Customer customer);
    
    }
    

    Automatically attaching JWTs

    Blazor can automatically attach JWT access tokens to your outgoing requests if you configure your Http Client to use AuthorizationMessageHandler.

    Under the hood this makes sure the authorization request header includes your Bearer access token (if you’re logged in to the application).

    Here’s how I was able to get that working with Refit.

    private static async Task Run(WebAssemblyHostBuilder builder, string[] args)
    {
        var apiUrl = "http://localhost:5001/api";    
    
        builder.Services.AddRefitClient<CustomerApi>()
            .ConfigureHttpClient(c => { c.BaseAddress = new Uri(apiUrl); })
            .AddHttpMessageHandler(sp => sp.GetRequiredService<AuthorizationMessageHandler>()
                .ConfigureHandler(new[] {apiUrl}));
        
        // other code...
    }
    

    The key is to make sure you configure the handler with the base address for your API (the call to ConfigureHandler).

    AuthorizationMessageHandler will only attach tokens when you make requests to a URI which starts with that Base URL.

    In summary

    You can cut down on some boilerplate code, reduce the number of magic strings and improve the discoverability of your API by using the handy Refit library.

    Find out more at the Refit Github repository.

    Join the Practical ASP.NET Newsletter

    Ship better Blazor apps, faster. One practical tip every Tuesday.

    I respect your email privacy. Unsubscribe with one click.

      Next up

      The quickest way to integrate PayPal checkout with Blazor SSR in .NET 8
      JavaScript Interop works differently with Blazor Server-side rendering
      Interactive what now? Deciphering Blazor’s web app project template options
      Create a new Blazor Web App and you’ll be asked how you want interactivity to work, but what does it all mean?
      Should I put my Blazor components in the server project, or the client project?
      .NET 8 gives you a choice of projects, which one should you use?