Different ways to implement IHttpClientFactory in .NET core apps
Tags: httpclient, dotnet, csharp, webdev
Published: 2022-02-28 10:32:34

## Why not HttpClient?

We have been using the `HttpClient` class for REST API calls and I am not saying this is bad practice but most of the times developer use it wrongly and it has some limitations which cause serious issues, I have noted a few of them:

- Even we dispose of instance underlying socket doesn't release immediately, which leads to [socket exhaustion](https://www.aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/).

```
using(var client = new HttpClient())
{
    //do something with HTTP client
}
```
Do you think creating an instance using the `using` block will work? The answer is it won't work. If you are curious about what is the current state or wanted to confirm that the underline socket is closed or not then run the below command and it will show a list of connections that are in a wait or established state.

```
> netstat -na | find 'Port_Number'
```
- To avoid socket exhaustion if you create a singleton or static instance throughout the application lifetime then it's not the ultimate solution because when you reuse the instance which means you are reusing the connection until the socket is closed. So the connection won't get updates from the server, effectively it will fail to handle DNS changes when we switch from `staging` to `production` environment. You can find more details [here](http://byterot.blogspot.com/2016/07/singleton-httpclient-dns.html).

- Creating an instance inside the `using` directive is not good practice as it tries to dispose of instances of `HttpClient` along with that it will dispose of the `HttpClientHandler` as well. Under the hood, `HttpClient` uses the `HttpClientHandler` for actual socket connection, but underhood implementation is out of scope for this article but I will create a separate detailed article on it.

To address the above issue .Net core introduced the `IHttpClientFactory` interface which we can use for `HttpClient` instance creation using DI.

## Different ways to use IHttpClientFactory:

**1. Basic usage:** 

You can register `IHttpClientFactory` using `AddHttpClient` extension method.
`Program.cs` or `Startup.cs`

```
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddHttpClient();
```
`TestController.cs`: DI will inject the dependency in the constructor.

```
class TestController : Controller
{
   private readonly IHttpClientFactory  _factory;

   public TestController(IHttpClientFactory factory)
   {
     _factory = factory;
   }

   [HttpGet]
   public async Task<IActionResult> Get()
   {
     var httpClient = _factory.CreateClient();
   }
}
```
**2. Named Clients:**

If you need a different configuration for each HttpClient then you can use named client DI and get an instance using the same name. Let's say you need to interact with 2 third-party APIs using HTTP REST calls and both need to be configured differently using the named client as below.

`Startup.cs`:
```
builder.Services.AddHttpClient("ClientA", httpClient =>
{
    httpClient.BaseAddress = new Uri("https://apiA.com/");
    //ToDo more configuration
});

builder.Services.AddHttpClient("ClientB", httpClient =>
{
    httpClient.BaseAddress = new Uri("https://apiB.com/");
    //ToDo more configuration
});
```

`TestController.cs`:

```
var httpClientA = _factory.CreateClient("ClientA");

var httpClientB = _factory.CreateClient("ClientB");
```

**3. Typed Clients**

It provides the same capabilities as the named client but instead of identifying the client based on the key it actually intelligently resolve HttpClient in a specific `HttpHandler` class. Another advantage of this approach is you don't need to create `HttpClient` manually using `IHttpClientFactory.CreateClient()` method.

Let's say you decided to write one custom `HttpHandler` which would be the single source for every REST call, so your implementation would look something like below.

`HttpCommands.cs`: 

```
public class HttpCommands
{
  private readonly HttpClient _httpClient;

  public HttpCommands(HttpClient httpClient)
  {
    _httpClient = httpClient;
  }
}
```
Look at the constructor we are injecting `HttpClient` itself and not `IHttpClientFactory`, which means `_factory.CreateClient()` is not required anymore because .Net core is smart enough to resolve the dependency.

`Startup.cs`: To register typed `HttpClient` using generic version of `AddHttpClient()` extension method.

```
services.AddHttpClient<HttpCommands>();

//Or if you need custom configuration you can configure that too as we did for the named client

services.AddHttpClient<HttpCommands>(client =>
{
  client.BaseAddress = new Uri("https://apiA.com/");
});
```

## Conclusion

- What are the issues in traditional `HttpClient` usage?
- What are the issues with the `static` or `singleton` `HttpClient` instance.
- What are the different ways to use the `IHttpClientFactory`.

Happy Coding!