HttpClient class can be easily used in a way how it’s not meant to be. While this class is disposable, using it with the
using statement is often not the best choice. Disposing the
HttpClient, the underlying socket is not immediately released. The
HttpClient class is designed to be reused for multiple requests. Having the need for different base addresses, different HTTP headers, and for error recovery, it helps having multiple instances.
To make the management of
HttpClient instances easier, .NET Core 2.1 offers a new HTTP Client Factory – which creates, caches, and disposes
HttpClient instances. This article demonstrates different ways on using the
Why it’s not a good idea to use the HttpClient class with the using statement is clearly demonstrated with this blog article from Simon Timms.
Using the IHttpClientFactory
To get rid of self-creating of
HttpClient instances, after adding the NuGet package Microsoft.Extensions.Http, the extension method
IServiceCollection is available. This extension method registers the
DefaultHttpClientFactory to be used as a singleton for the interface
IHttpClientFactory. It defines a transient configuration for the
HttpMessageHandlerBuilder. This message handler is used by the
HttpClient returned from the factory.
You can call
AddHttpClient multiple times – with different configurations. The sample code defines the name cni for HttpClients using the base address
https://www.cninnovation.com. You can also add HTTP headers that should be used with all the HttpClient instances from this group.
With the class where the
HttpClientshould be used, the
IHttpClientFactory is injected in the constructor. From there, the
HttpClient is retrieved by invoking the
CreateClient method of this interface. Depending on the different HttpClient instances needed, the
HttpClient can be retrieved in the constructor of the class, or in the method where the
HttpClient is used. You don’t need to deal with the HTTP headers needed, or the base address – just the name of the registration needs to be used invoking the
CreateClient method to get the
HttpClient with the correct configuration.
Disposing of the
HttpClientcan be done, but is not required. Disposing of the
HttpClientcancels any outgoing request and ensures that the
HttpClientcannot be used after disposing. The factory itself tracks, caches, and disposes resources used by the
HttpClient, that’s why disposing is not required.
Using a Typed Client
Another way on using the factory is by using a typed client. A typed client makes use of a
HttpClient with a specific configuration, and the
HttpClient is injected in the constructor. With the following code snippet, in the TypedClient class, the
HttpClient is injected in the constructor, and used like before in the CallServerAsync method.
With the dependency injection container configuration, now the method
AddTypedClient is invoked passing the TypedClient class. This is an extension method for the
IHttpClientBuilder interface, and thus can be used with the return value of the
AddHttpClient method. This way, the configuration of the
HttpClient maps to the typed client.
With this factory, The Polly Project can be used to handle faults. The NuGet package Microsoft.Extensions.Http.Polly offers extension methods to use Polly with the factory.
IHttpClientBuilder returned from the method
AddHttpClient, policies can be defined. Invoking the method
AddPolicyHandler passing the
Policy.TimoutAsync policy, the timout can be specified used by the
AddTransientHttpErrorPolicy deals with transient errors – network failures and HTTP 5xx and HTTP 408 errors. The code sample makes use of the wait and retry policy and passes three different timespans – 1, 5, and 10 seconds. If a transient error occurs, a retry is done after 1 second. If the error still happens after 1 second, retries happen after 5 and 10 seconds. If the error still happens after 10 seconds, an exception is thrown that is dealt with when using the
The Polly Project offers rich policies to handle errors.
Using a HttpClientHandler
The HTTP Client Factory offers a lot ways for customization. One way is to add a
HttpClientHandler that you are used to pass to the constructor of the
HttpClient with the
To define to use a
HttpClientHandler, you just need to invoke the method
ConfigureHttpMessageHandlerBuilder, and return a
HttpClientHandler from the implemention of the delegate parameter. Here, you can configure the
HttpClientHandler, e.g. with automatic decompression:
The HTTP Client Factory fixes issues on using the
HttpClient and make it easy to use it with different configurations needed – including policies to specify retry logic on errors. Using the
HttpClient, it just needs to be injected in the classes where you need this type. Microsoft.Extensions.Http gives you extension methods to integrate with the .NET Core dependency injection container, and Microsoft.Extensions.Http.Polly offers an integration to the Polly Project.
The complete Source code is available at Github.