简体   繁体   中英

Correct usage of IHttpClientFactory for a .net-core transient service

I'm looking into using IHttpClientFactory for calling external APIs in my asp.net core app. I've seen a few examples where the client factory is created in the constructor of the service's class. Then the methods of that class, call that client factory to generate an instance of HttpClient to make Http requests. Like the following sample code:

public class MyTransientService: IMyService
{
    private readonly IHttpClientFactory _clientFactory;

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

    public async Task<MyData> GetData()
    {
        //construct the request
        var httpClient = _clientFactory.CreateClient();
        var response = await client.SendAsync(request);
        ...
    }
}

If the service is registered as transient in startup.cs, wouldn't a new instance of HttpClientFactory be generated each time that the service is called? A new HttpClientFactory per request? So wouldn't the following be a more efficient way to use the factory?

public class MyTransientService: IMyService
    {
        private readonly HttpClient _client;
    
        public MyTransientService(
            HtpClient client
        )
        {
            _client = client;
        }
    
        public async Task<MyData> GetData()
        {
            Uri uri = new Uri(StaticUtils.AddQueryString(url, props));
            var response = await _client.SendAsync(request);
            ...
        }
    }

I would consider creating the HttpClient yourself bad practice, on self you have control of how many is created. If MyTransientService is transient, you will end up creating a lot of socket connections (one for each instance/request) HttpClient is created to be reused.

Take a look at Typed clients: https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient("hello", c =>
    {
        c.BaseAddress = new Uri("http://localhost:5000");
    })
    .AddTypedClient<MyTransientService>();

    services.AddControllers();
}

public class MyTransientService: IMyService
{
    private readonly HttpClient _client;

    public MyTransientService(
        HtpClient client
    )
    {
        _client = client;
    }

    public async Task<MyData> GetData()
    {
        Uri uri = new Uri(StaticUtils.AddQueryString(url, props));
        var response = await _client.SendAsync(request);
        ...
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM