Injected HttpClient ignores IHttpClientFactory configuration

。_饼干妹妹 提交于 2020-08-02 05:32:43

问题


I've created a custom library which automatically sets up Polly policies for specific services which depend on HttpClient.

This is done using the IServiceCollection extension methods and the typed client approach. A simplified example:

public static IHttpClientBuilder SetUpFooServiceHttpClient(this IServiceCollection services)
{
    return services
            .AddHttpClient<FooService>()
            .AddPolicyHandler(GetRetryPolicy());
} 

The example service:

public class FooService
{
    private readonly HttpClient _client;

    // OPTION 1
    public FooService(HttpClient httpClient)
    {
        _client = httpClient;
    }

    // OPTION 2
    public FooService(IHttpClientFactory httpClientFactory)
    {
        _client = httpClientFactory.CreateClient(GetType().Name);
    }

    public void DoJob()
    {
         var test = _client.GetAsync("http://example.com");
    }
}

Fetching the service from the DI container (this is from a test project):

var services = new ServiceCollection();

services.SetUpFooServiceHttpClient();
        
services.AddSingleton<FooService>();

var fooService = services
                   .BuildServiceProvider()
                   .GetRequiredService<FooService>();

// Perform test
fooService.DoJob();

Note: In this test project, I also add an extra mocked handler since I'm trying to mock http status responses, but the mocked handler being present or not is identical to the Polly policy being present or not, so I omitted the mocked handler from the example code.

Notice the two different constructors in FooService. Depending on which one I comment out and which one I leave in, I get different outcomes. All other code remains untouched.

  • Option 1, injecting the HttpClient directly, ignores all my configuration. I get a standard http client with no Polly policy handler.
  • Options 2, injecting the IHttpClientFactory and requesting the client using the current type name (i.e. FooService) respect my configuration. I get a custom http client which contains the Polly policy handler (and any other handlers I may have configured, e.g. mocked handlers in my test suite)

The absence/existence of the policy handler is confirmed in both cases using debug inspection.

According to all documentation I've found on the subject, both options should be equivalent, at least in regards to the constructed HttpClient that I obtain in the end. But that is not the case here.

The documentation I find specifies that HttpClient can be injected when using typed clients:

  • The MSDN documentation, specifically the "typed clients" section example.
  • This SO answer
  • This blog post

I'm using a typed client but injecting a HttpClient clearly doesn't work for me.

Why does injecting a HttpClient vs injecting IHttpClientFactory work differently in my case?


回答1:


In effect, you have the following two registrations for your FooService class:

  1. services.AddHttpClient<FooService>()
  2. services.AddSingleton<FooService>();

Because of how the DI container works behind-the-scenes, the second registration overwrites the first. If you remove the second registration, the first will be used, and so your constructor with the HttpClient parameter will be invoked.



来源:https://stackoverflow.com/questions/63056470/injected-httpclient-ignores-ihttpclientfactory-configuration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!