.NET Core: Use HttpClientFactory and Polly to build rock solid services
Tags: csharp, dotnet, dotnetcore, polly
Published: 2020-05-25 07:09:11

---
title: .NET Core: Use HttpClientFactory and Polly to build rock solid services
published: true
description: In this post I will explain what is HttpClientFactory and Polly retry polices and why you should use them in your next project
tags: csharp, dotnet, dotnetcore, polly
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/4avi744cnmt2z4l39o8t.png
---

In this post I will explain what is HttpClientFactory and Polly retry policies and why you should use them in your next project.

# Let's start with `IHttpClientFactory`

A lot of clients call me to help them resolve issues regarding sudden and random request failures. They put a new service in production, it works fine  for the first few days, but out the the blue they start seeing a lot of [SocketException](https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socketexception?view=netcore-3.1) in their [Application Insights](https://docs.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview).

Most of the time these failures are the result of **wrong usage of HttpClient** that is causing **_socket exhaustion_**.

**HttpClient** is intended to be instantiated once and reused throughout the life of an application. Instantiating an **HttpClient** class for every request will exhaust the number of sockets available under heavy loads.

So please avoid using code like this:

```csharp
using (var httpClient = new HttpClient())
{
    var result = await httpClient.GetAsync("https://www.bing.com");
}
```

You can read more details about this issue here:
https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/


So, in order to mitigate this problem the .NET Core team introduced in .NET Core 2.1 the [IHttpClientFactory](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1) that provides the following benefits:

1. Provides a central location for naming and configuring logical HttpClient objects. For example, you may configure a client (Service Agent) that's pre-configured to access a specific microservice.

2. 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.

3. HttpClient already has the concept of delegating handlers that could be linked together for outgoing HTTP requests. You can register HTTP clients into the factory and you can use a Polly handler to use Polly policies for Retry, CircuitBreakers, and so on.

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


So let's see a very simple example that leverages IHttpClientFactory.
In my example, I will use a very cool and free API the [SuperHero](https://superheroapi.com/) (you can find many more free APIs to play around at https://apilist.fun/).

In a new Web API project, go to `Startup.cs` change `ConfigureServices` method like this:

```csharp
public void ConfigureServices(IServiceCollection services)
{
    // the AddHttpClient() will provide us with an instance of HttpClient
    // available for Dependancy Injection in our services
    services.AddHttpClient<ISuperHeroService, SuperHeroService>(o =>                                    
                          o.BaseAddress = new Uri(Configuration["SuperHeroApiConfig:BaseUrl"]));
    
    services.AddControllers();
}
```

Let's create now our `SuperHeroService`:

```csharp
public class SuperHeroService : ISuperHeroService
{

    private readonly HttpClient _httpClient;
    private readonly ISuperHeroApiConfig _superHeroApiConfig;

    public SuperHeroService(HttpClient httpClient, ISuperHeroApiConfig superHeroApiConfig)
    {
         _httpClient = httpClient;
         _superHeroApiConfig = superHeroApiConfig;
    }

     public async Task<PowerStats> GetPowerStats(int id)
     {
         return await _httpClient.GetFromJsonAsync<PowerStats>(
                $"{_superHeroApiConfig.AccessToken}/{id}/powerstats");
     }        
}
```

Last but not least let's create our `SuperHeroController`:

```csharp
[ApiController]
[Route("api/[controller]")]
public class SuperHeroController : ControllerBase
{
    private readonly ILogger<SuperHeroController> _logger;
    private readonly ISuperHeroService _superHeroService;

    public SuperHeroController(ILogger<SuperHeroController> logger, ISuperHeroService superHeroService)
    {
        _logger = logger;
        _superHeroService = superHeroService;
    }

     [HttpGet("GetPowerStats/{id}")]
     public async Task<ActionResult> GetPowerStats(int id)
     {
         var result = await _superHeroService.GetPowerStats(id);

         return Ok(result);
     }       
}
```
You can use Postman or any other app to test your Super Hero service:

![Postman example](https://dev-to-uploads.s3.amazonaws.com/i/v1p896jw0rmxnrixwacr.PNG)

Now that we saw how easy it is to overcome the old HttpClient issues with `IHttpClientFactory`, let's make our Super Hero service more resilient to failures using [Polly](https://github.com/App-vNext/Polly).

# Polly

> Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner.

I think most of us, at some point in time, we saw code like this, trying to implement some kind of retry logic.

```csharp
public async Task<PowerStats> GetPowerStats(int id)
{
      var currentRetry = 0;

       while (true)
       {
            try
            {
                return await _httpClient.GetFromJsonAsync<PowerStats>(
                                $"{_superHeroApiConfig.AccessToken}/{id}/powerstats");

             }
             catch (Exception ex)
             {
                currentRetry++;

                 if (currentRetry > 3)
                 {
                     throw;
                 }
            }
        }
}
```

However, we can all agree that this approach is not clean and easily maintainable, especially in a big project with many different services and endpoints.

## **`Polly`** comes to the rescue!

**Step 1:** Add the **Polly** nuget pachage `Microsoft.Extensions.Http.Polly`.

**Step 2:** Create your custom policy inside `ConfigureServices` method of `Startup.cs`.

```csharp
// Create the retry policy we want
var retryPolicy = HttpPolicyExtensions
                .HandleTransientHttpError() // HttpRequestException, 5XX and 408
                .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(retryAttempt));
```

**Step 3:** Apply it to our SuperHeroService, it's super easy!

```csharp
services.AddHttpClient<ISuperHeroService, SuperHeroService>(o => 
                            o.BaseAddress = new Uri(Configuration["SuperHeroApiConfig:BaseUrl"]))
                .AddPolicyHandler(retryPolicy);
```

So what will happen now when our SuperHeroService gets a `TransientHttpError` (HttpRequestException, 5XX, 408) ?

Our **HttpClient** will retry the request.
The 1st time it will wait 1 second and retry.
The 2nd time it will wait 2 seconds and retry.
The 3rd and last time it will wait 3 seconds and retry.
If it fails again it will not retry and just return.

This is a very simple example just to demonstrate basic `Polly` usage, but you can do many more things.
You can tailor your retry policies as you see fit, apply Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback with just a few lines of code.

Now you have the knowledge to build a rock solid service, use it!

You can find the full code on my [GitHub](https://github.com/Rickinio/HttpClientFactoryPollyExample)

This post was written with love ❤️