Search code examples
c#dependency-injection.net-6.0dotnet-httpclient

How is HttpClient injected into a ctor?


I found this ctor:

public class MobileOtpService : IMobileOptService
{
    private readonly HttpClient _client;

    public MobileOtpService(HttpClient client) // How is this injected?
    {
        _client = client;
    }
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IMobileOptService, MobileOtpService>();
        ...
        services.AddHttpClient();
    }
}

I can't find any hard-coded instantiations of MobileOtpService, so it must just be using DI.

How is the HttpClient injected?

Does this happen automatically because of services.AddHttpClient()?

I can't find any code that sets the BaseAddress etc.


Solution

  • There are many ways to register and use HttpClients. Let me list here the options:

    Default client

    This option can be used to get an HttpClient with default settings.

    Registration

    services.AddHttpClient();
    

    Usage

    private readonly HttpClient uniqueClient;
    public XYZService(IHttpClientFactory clientFactory)
      => uniqueClient = clientFactory.CreateClient();
    

    Named client

    This option can be used to get a preset HttpClient.

    Registration

    services.AddHttpClient("UniqueName", client => client.BaseAdress = ...);
    

    Usage

    private readonly HttpClient uniqueClient;
    public XYZService(IHttpClientFactory clientFactory)
      => uniqueClient = clientFactory.CreateClient("UniqueName");
    

    Typed client

    This option can be used to wrap a default/preset HttpClient into a higher-level abstraction.

    Registration

    services.AddHttpClient<UniqueClient>();
    services.AddHttpClient<IUniqueClient, UniqueClient>(client => client.BaseAdress = ...);
    

    Usage

    private readonly HttpClient httpClient;
    public UniqueClient(HttpClient client)
      => httpClient = client;
    
    private readonly IUniqueClient uniqueClient;
    public XYZService(IUniqueClient client)
      => uniqueClient = client;
    

    Named and Typed client

    This option can be used to register different preset HttpClients and wrap them into a higher-level abstraction.

    Registration

    services.AddHttpClient<IUniqueClient, UniqueClient>("primary", client => client.BaseAdress = ...);
    services.AddHttpClient<IUniqueClient, UniqueClient>("secondary", client => client.BaseAdress = ...);
    

    Usage

    private readonly HttpClient httpClient;
    public UniqueClient(HttpClient client)
      => httpClient = client;
    
    public XYZService(
       IHttpClientFactory namedClientFactory, 
       ITypedHttpClientFactory<UniqueClient> namedTypedClientFactory)
    {
        var namedClient = namedClientFactory.CreateClient("primary");
        var namedTypedClient = namedTypedClientFactory.CreateClient(namedClient);
    }
    

    If you are interested about their lifecycle management then please check out this SO topic.