HttpClient vs IHttpClientFactory

Henrique Siebert Domareski
5 min readAug 27, 2022

--

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

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 HttpClient is created for every single request
  • The same HttpClient is 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 HttpClient implements 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 appsettings.json file:

IHttpClientFactory

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.

Named Clients

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.

IHttpClientFactory Benefits

  • Exposes HttpClient class as DI ready type.
  • Provides a central location for naming and configuring logical HttpClient instances.
  • 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:

https://github.com/henriquesd/HttpRequestExamples

If you like this project, I kindly ask you to give a ⭐️ in the repository.

Thanks for reading!

--

--