EDIT: This article has been originally published for .NET Core 3.1 — Preview2. .NET Core 3.1 Preview 3 introduces a breaking change that requires a slightly more clunky code in order to work.
When we create a single page web application with Blazor WebAssembly, it comes with a pre-configured
HttpClient service in the IoC container. This means that we can simply inject an
HttpClient dependency in our components and it will just work.
However, in a real world application, we might need something a bit more sophisticated than this and want to use
Why would we want to do that? At least for three reasons:
- interacting with different services, that have different base addresses and require different named clients;
- configure a strongly typed client for a given service and use that instead of the plain and simple HttpClient;
- use a library like Polly to define some policies that we want to apply to our network requests, such as retry, failover or circuit breaker.
Note: one of the main reasons you want to use IHttpClientFactory is because it controls the lifecycle of the HttpClient instances. Although this is perfectly valid for server-side code (and you should do it if you’re not doing it yet), this doesn’t apply to Blazor WebAssembly: in fact, when Blazor runs in a browser, it uses a special type of MessageHandler which wraps the browser’s XmlHttpRequests.
The good news is that this is all achievable in Blazor WebAssembly, and frankly seeing all of this running in the browser is quite mind-blowing. The (slightly) bad news is that at it’s not there (yet?) out of the box, and requires some plumbing. Please note that this might change in the near future, as we get closer to the final release of Blazor WebAssembly.
So how do we configure it in Blazor? Keep reading :)
Now, let’s assume you have created a brand new Blazor WebAssembly project. The first step is adding a reference to the
Microsoft.Extensions.Http package and (optionally) to
Then, we can head to the
ConfigureServices method in Startup, and start configuring the IoC container:
There are a few things going on in the above snippet:
- we remove the HttpClient service the default builder has already configured for us: we won’t need it as we’re going to use IHttpClientFactory for this;
- we register a
WasmHttpMessageHandlerservice as scoped. This is the special handler Blazor uses in order to execute HTTP calls through the browser. The “server side” WebRequestHandler is obviously not an option in the WebAssembly world as it leverages some operating system’s primitives;
- we then add an example of a named client by configuring a “local” HttpClient instance, which uses the application’s Url as it’s base address. As you can see, when doing it, we also specify the message handler we want to adopt by using the
- in order to be backwards compatible, and support all the components that inject an HttpClient directly, we can register an HttpClient service which we internally create through the factory.
Note: before .NET Core Preview 3, the Blazor was exposing a
WebAssemblyHttpMessageHandlertype as part of the class library. This has now been removed and the framework is using
WasmHttpMessageHandler, which is part of Mono — and not directly referenced by any Blazor packages. In order to preserve the independence from the version of the runtime, we are using reflection to register it, regardless to whichever version of
WebAssembly.Net.Httpis in the execution context.
All done, if you do Ctrl-F5 now, your Blazor application should work just fine, although using IHttpClientFactory under the hood to inject an HttpClient instance.
Sounds cool, what now?
Now that we have the basic infrastructure in place, we can finally start leveraging some of the cool functionalities we’ve mentioned at the beginning of the article.
For example, we can easily create a strongly typed client for the WeatherForecast web service like the following:
and then configure it in the IHttpClientFactory:
The benefit of this, apart from having strongly typed parameters and methods to call, is also that we can set the base address for the service in a centralised way. If we think about a scenario in which we are interacting with a number of different web services, each of them with its own base address, we can obviously understand how elegant and powerful this solution is, rather than specifying the absolute URL in each call.
The other great benefit I’ve mentioned is being able to define policies through the use of Polly, that can apply to certain calls.
For example, we can easily modify the typed client configuration above, to integrate a simple retry logic:
In this way, should an error happen during the call, Polly will automatically retry it up to ten times, before raising an exception.
IHttpClientFactory offers some very powerful features that are pretty much required in every real world application. Even though Blazor WebAssembly doesn’t support it in its default configuration, we can easily add the relevant packages and configure our project to use it.
This allows us to encapsulate the configuration of the different services we want to interact with in a centralised class, define and use strongly typed clients and even injecting complex behavioural policies by using Polly.
Obviously, being Blazor WebAssembly still in preview, please don’t forget that what we’ve seen in this article is subject to change in the future.