HttpClient and IHttpClientFactory can be used in .NET to make HTTP requests and handle HTTP responses from web resources. In this article, I explain how to use each of them and what is the difference between them.
For the code samples, I’ve created a .NET 6 Web API project, which makes requests to CoinDesk’s public API. The complete project code can be found here.
HttpClient is a class that can be used for making HTTP requests and handling HTTP responses from web resources identified by a Uri in .NET. The HttpClient type was introduced in .NET Framework 4.5 (which was released in 2012) and is also available in .NET Core and .NET 5+.
Two ways that
HttpClient was commonly used were:
- A new
HttpClientis created for every single request
- The same
HttpClientis used for all requests
The problem of creating a
HttpClient for each request, is that there is an overhead of instantiation, and beyond that, each
HttpClient will hold open the socket that it used for some time after the request is completed. In case you have made a high volume of requests, you can face a socket exhaustion issue (it’s when a new
HttpClient cannot acquire a socket to make a request). It’s true that when we use the
HttpClient object inside of a
using code block, the HttpClient object is disposed after it is used (because
IDisposable), however, the socket connection is not, and this can lead to a socket exhaustion problem when your traffic increases.
A better approach to use
HttpClient, is to create your HttpClient object as singleton or static, instead of wrapping your HttpClient in a using, this way you will have a single instance of
HttpClient for a given endpoint. But even with this approach, it’s better to configure the connection pooling behavior by configuring the
PooledConnectionLifetime (this allows you to define how long a connection remains active when pooled, and once this lifetime expires, the connection will no longer be pooled or issued for future requests — It gets or sets how long a connection can be in the pool to be considered reusable), otherwise if the DNS TTL (time to live — is a setting that tells the DNS resolver how long to cache a query before requesting a new one) is expired and the domain name points to a new IP, your code will never know until it restarts, since there is no default logic in
HttpClient to handle that. In the code below there is an example of how to do that:
On line 6 there is a static property for the
HttpClient, where it is configured the PooledConnectionLifeTime for 1 minute. On line 14 we get the API Url from the
appsettings.json file. On line 21 the request is being made.
The API Url is configured in the
IHttpClientFactory was introduced in .NET Core 2.1 (also available in .NET 5+) and it provides a much-improved approach for getting an HTTP client.
IHttpClientFactory can take advantage of resilient and transient-fault-handling third-party middleware with ease. It serves as a factory abstraction that can create
HttpClient instances with custom configurations.
IHttpClientFactory solves both problems that were previously mentioned in the HttpClient topic, and this is done by pooling the
HttpClientHandler (which does most of the work of
HttpClient) and also dispose of
HttpClientHandlers after a specified period. When a new
HttpClientHandler is created for an endpoint, A DNS lookup is performed, with that you won’t wear out the sockets and you will get a new IP address for each endpoint.
How to use
The first thing that must be done in order to use
IHttpClientFactory, is to register it by calling
AddHttpClient via Dependency Injection (it will be registered in the service collection as a singleton). In the Program.cs file, you can register like this:
Once registered, now the class that will make use of
IHttpClientFactory can receive it as a constructor parameter with DI. In the code below there is an example of how to use it:
Note that on line 8,
IHttpClientFactory is part of the constructor parameter, and we have a private variable to be used in this class. On line 11 we get the API Url from the appsettings.json file. On line 19 there is a call to
CreateClient, this is a
IHttpClientFactory method which returns the HttpClient Object. On line 22 the request is executed.
It’s also possible to have named clients, you can do that by registering it via DI (you can register how many you want). This is how you can configure it in a Program.cs file:
This is how you can use the named client in your class:
As in the previous example,
IHttpClientFactory is part of the constructor parameter, and we have a private variable to be used in this class (line 3). On line 14 there is a call to
CreateClient, but now with the name that was configured via DI. On line 16 the request is executed.
There are also other ways to work with
IHttpClientFactory, if you want to know more about it, check the Consumption patterns at Microsoft Docs.
HttpClientclass as DI ready type.
- Provides a central location for naming and configuring logical
- Integrates well with Polly (a .NET resilience and transient-fault-handling library).
- Avoid common DNS problems by managing HttpClientHandler lifetimes.
- Adds configurable logging (via
ILogger) for all the requests sent through clients created by the factory.
For most cases, the best approach for making requests to external API is by using IHttpClientFactory. Microsoft’s recommendation is to use IHttpClientFactory or use a static or singleton HttpClient with PooledConnectionLifetime configured with the desired interval. You can check the complete code of this project here:
If you like this project, I kindly ask you to give a ⭐️ in the repository.
Thanks for reading!