HttpClient Retry with .NET Core, Polly, and IHttpClientFactory

By FoxLearn 1/9/2025 3:15:23 AM   121
Many HTTP errors are temporary and caused by issues such as server overload, network timeouts, or transient glitches.

These scenarios can be managed using a retry pattern. In .NET Core, one of the most popular libraries for implementing retry logic is Polly.

Polly is a .NET resilience library that helps developers define fault-handling policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent, thread-safe way. Starting from version 6.0.1, Polly supports .NET Standard 1.1 and 2.0+.

Polly simplifies retry logic implementation when used with IHttpClientFactory and IHttpClient.

Install Necessary NuGet Packages

You need the following NuGet packages:

  • Polly
  • Microsoft.Extensions.Http.Polly

Configure Services in Startup.cs

In the ConfigureServices method, add IHttpClientFactory and attach the retry policy via a PolicyHandler:

// ConfigureServices() - Startup.cs
services.AddHttpClient("HttpClient").AddPolicyHandler(GetRetryPolicy());

private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
    return HttpPolicyExtensions
        // Handle HttpRequestExceptions, 408 and 5xx status codes
        .HandleTransientHttpError()
        // Handle 404 not found errors
        .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
        // Handle 401 Unauthorized errors
        .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.Unauthorized)
        // Retry 3 times with exponential backoff (1s, 2s, 4s)
        .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}

Using IHttpClientFactory in the Calling Class

You can inject IHttpClientFactory into your class. The magic of Polly is that your HTTP client logic does not need to handle retries manually you simply make the usual Get or Post calls, and Polly will automatically apply the retry policy.

namespace MyApp
{
    public class MyClass
    {
        private readonly IHttpClientFactory _clientFactory;

        public MyClass(IHttpClientFactory clientFactory)
        {
            _clientFactory = clientFactory;
        }

        public async Task<int> PostMessageAsync(string postData)
        {
            var httpClient = _clientFactory.CreateClient("HttpClient");

            using (var content = new StringContent(postData, Encoding.UTF8, "application/json"))
            {
                var result = await httpClient.PostAsync($"{url}", content);

                if (result.StatusCode == HttpStatusCode.Accepted)
                {
                    return result.StatusCode;
                }
                else
                {
                    // Handle failure
                    return result.StatusCode;
                }
            }
        }
    }
}

In this example, the httpClient.PostAsync() method automatically retries the request if any of the conditions defined in the GetRetryPolicy() method occur. The retry process will continue until the request is either successful or the maximum retry count is reached.

By combining Polly with IHttpClientFactory, you can effectively handle transient HTTP errors with minimal code and ensure better resilience in your application.