.netdependency-injection

Is it wrong to use HttpClientFactory in a singleton service?


I read this article about HttpClientFactory. But i couldn't find a answer for my question. Is it bad approach to use HttpClientFactory in a singleton service to send request to somewhere?

My Program.cs:

builder.Services.AddSingleton<TestService>();
builder.Services.AddTransient<HttpRequestDelegatingHandler>();


builder.Services.AddHttpClient("test", client =>
{
    client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com");
}).AddHttpMessageHandler<HttpRequestDelegatingHandler>();

And my Test Service:

public class TestService
{
    public Guid InstanceId { get; } = Guid.NewGuid();

    private readonly **IHttpClientFactory _factory;**
    private readonly ILogger<TestController> _logger;

     public TestService(IHttpClientFactory factory, ILogger<TestController> logger)
    {
        **_factory = factory;**
        _logger = logger;
    }

    public async Task<string> GetAsync()
    {
        // Get the scoped service's ID
        _logger.LogInformation("Service ID in controller {InstanceId}", InstanceId);

        // Retrieve an instance of the test client, and send a request
        var client = _factory.CreateClient("test");
        var result = await client.GetAsync("posts");

        // Just return a response, we're not interested in this bit for now
        result.EnsureSuccessStatusCode();
        return await result.Content.ReadAsStringAsync();
    }
} 

I created a delegating handler to understand what is going on and i didn't notice any issues.


Solution

  • It is fine to use IHttpClientFactory inside a Singleton service, As a side point, all HttpClient instances that are created by the client factory are meant to be short-lived, then better to use using statement like this:

    public async Task<string> GetAsync()
        {
            //...
    
            // make sure the httpclient will be disposed
            using var client = _factory.CreateClient("test");
            var result = await client.GetAsync("posts");
    
            // ...
        }
    

    Please consider reading this MS doc as well:

    https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines#recommended-use