Using HttpClientFactory

We all have used HttpClient in some point of our career, special when you consume APIs. HttpClient has been with us since .Net Framework 4.5. Now, with ASP.NET Core 2.1 HttpClientFactory allow us to solve multiple problems that the predecessor has.

One of those issues is known as “sockets exhaustion“, when using HttpClient with using statement even though things are being disposed. When you run netstat you’ll see connections with TIME_WAIT state which basically means that connection have not fully closed. They’re waiting for additional packets. One other example is when you use it as a Singleton, which in fact will increase performance and fix the previous issue, but now you have the issue of not respecting the DNS Time to Live (TTL) settings. HttpClientFactory fixes these problems and many other, but let’s move on to what HttpClientFactory give us.

Provide a central location for naming and configuring logical HttpClients. For example, you may configure a client (Service Agent) that’s pre-configured to access a specific microservice.

Codify the concept of outgoing middleware via delegating handlers in HttpClient and implementing Polly-based middleware to take advantage of Polly’s policies for resiliency.

Manage the lifetime of HttpClientMessageHandlers to avoid the mentioned problems/issues that can occur when managing HttpClient lifetimes yourself.

HttpClient already has the concept of delegating handlers that could be linked together for outgoing HTTP requests. You register http clients into the factory plus you can use a Polly handler that allows Polly policies to be used for Retry, CircuitBreakers, etc.

There are 3 ways you can use HttpClientFactory. One, using it Directly. second, Named Clients, and of course making your on by using Typed Clients

Using HttpClientFactory Directly

On Startup.cs, in the ConfigurationServices method. Add the following

services.AddHttpClient();

Now, to consume that service on the controller keep doing dependency injection as it shows

public class ValuesController : Controller
{
    private readonly IHttpClientFactory _HttpClientFactory;
  
    public ValuesController(IHttpClientFactory httpClientFactory)
    {
        _HttpClientFactory = httpClientFactory;
    }
  
    [HttpGet]
    public async Task<IActionResult> Get()
    {
        var client = _HttpClientFactory.CreateClient();
        client.BaseAddress = new Uri("YOUR URL");
        var result = await client.GetStringAsync("/");
        return Ok(result);
    }
}

Using HttpClientFactory by Named Clients

Using HttpClientFactory by Named Clients is very useful, specially when you have request to multiple places. Let’s say that we have to process payments with 2 different providers. Paypal and Authorize.NET.

On Startup.cs, in the ConfigurationServices method. Add the following

services.AddHttpClient("paypal", c =>
{
    c.BaseAddress = new Uri("PAYPAL URL");
    c.DefaultRequestHeaders.Add("Accept", "application/json");
    c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactoryPaypal");
});
services.AddHttpClient("authorizenet", c =>
{
    c.BaseAddress = new Uri("AUTHORIZE NET URL");
    c.DefaultRequestHeaders.Add("Accept", "application/json");
    c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactoryauthorizenet");
});

As you can see Named Clients allow us to pre-configure which for this example is very useful. This pre-configuration can allow me to have on connection works with XML and another that works with JSON. I could add re-tries to one and request timeout to another one.

And following with DI, we consume it as shown below. we tell the factory which client we want by name.

public class ValuesController : Controller
{
    private readonly IHttpClientFactory _HttpClientFactory;
  
    public ValuesController(IHttpClientFactory httpClientFactory)
    {
        _HttpClientFactory = httpClientFactory;
    }
  
    [HttpGet]
    public async Task<IActionResult> Get()
    {
        var client = _HttpClientFactory.CreateClient("paypal");
        var result = await client.GetStringAsync("/");
        return Ok(result);
    }
}

Using HttpClientFactory by Typed Clients

Using Typed Clients basically refers at creating you own type. You can register your type in services as shown below.

services.AddHttpClient<IHttpPaypalClient, HttpPaypalClient>();

I personally recommend to use this approach if you are doing more than just requests and response operations. For example, you are massaging the incoming data in a different model. Some conversion to other types, etc. My point is that Typed Clients allow us to have a more robust HttpClient by encapsulating Http calls and all related logic, since is typed object we are no using string to get a specific HttpClient.

Now, we keep doing Dependency Injection on the controller

public class ValuesController : Controller
{
    private readonly IHttpPaypalClient _PaypalClient;
     
    public ValuesController(IHttpPaypalClient httpClient)
    {
        _PaypalClient = httpClient;
    }
     
    [HttpGet]
    public async Task<IActionResult> Get()
    {
        var result = await _PaypalClient.GetLastMonthPurchasesAsync();
        return Ok(result);
    }
}

In conclusion, HttpClientFactory give us a whole new level to work with Http calls. It adds simplicity and customization which solve know HttpClient issues.


References
https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests

Spread the word
  • Yum