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

Published on

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:

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.

Legacy .NET web apps causing you grief?

Build modern, reliable web applications, faster with .NET and Blazor.

Build better .NET web apps

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.

I know you don't have endless hours to learn ASP.NET

Cut through the noise, simplify your web apps, ship your features. One high value email every week.

I respect your email privacy. Unsubscribe with one click.

    Next Up
    1. With so many Blazor Component Libraries, which one is best for you?
    2. Does .NET 6 fix Blazor Prerendering?
    3. Persisting your users preferences using Blazor and Local Storage