Martin Volek
Martin Volek

Reputation: 1119

Resolve service in HttpContext configure Action

In asp.net core I am registering typed HttpClient and I need resolve service from service provider. How can I resolve services there?

Example:

services
    .AddHttpClient<TTypedHttpClient, TTypedHttpClientImpl>(httpClient =>
    {
        // how to resolve service on next line?
        var config = RESOLVE_SERVICE<IConfig>();
        httpClient.BaseAddress = config.GetBaseUrl();
    });

Upvotes: 0

Views: 2178

Answers (1)

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131749

I assume the actual question is how to access configuration or any other service when registering a typed HttpClient and HttpContext (the context of a specific HTTP request) isn't relevant.

UPDATE In .NET Core 2.1 AddHttpClient doesn't have an overload with two type parameters and aIServiceCollection despite what the documentation shows. The same job is performed by caling ConfigureHttpClient after AddHttpClient.

services
    .AddHttpClient<TTypedHttpClient, TTypedHttpClientImpl>()
    .ConfigureHttpClient(svc,httpClient =>
    {
        // how to resolve service on next line?
        var config = svc.GetRequiredService<IConfig>();
        httpClient.BaseAddress = config.GetBaseUrl();
    });

Original

You can use the AddHttpClient(IServiceCollection, String, Action< IServiceProvider,HttpClient>) overload to pass an IServiceProvider to the action that can be used to resolve other services :

services
    .AddHttpClient<TTypedHttpClient, TTypedHttpClientImpl>((svc,httpClient =>
    {
        // how to resolve service on next line?
        var config = svc.GetRequiredService<IConfig>();
        httpClient.BaseAddress = config.GetBaseUrl();
    });

I'd suggest reading Steve Gordon's article series on typed HttpClients and HttpClientFactory. Using Typed Clients from Singleton Services shows how to use AddHttpClient to configure the client. The rest of his articles show how to configure it with HttpClientFactory and Polly for correct pooling and retries

Configuration

Steve Gordon's example uses IOption to read the data from the configuration infrastrucure.

services.AddHttpClient<IConfigurationService, ConfigurationService>()
.ConfigureHttpClient((serviceProvider, client) =>
{
    var baseAddress = serviceProvider.GetRequiredService<IOptions<SdkOptions>>().Value.BaseAddress;
    client.BaseAddress = new Uri(baseAddress);
});

That's a good idea - HttpClient registration shouldn't know and shouldn't depend on the souce of its config values. IConfig should be nothing more than a configuration DTO loaded in the configuration phase.

.NET Core configuration can load values from json/xml/ini files, databases, external services, environment variables, anything that can return values in "section:subsection" - value form. It also allows combining and overloading settings, which can be very useful.

I have applications that load settings from files (basic configuration), databases managed by other teams (external service endpoints and credentials) and the command line (possible overrides). The endpoint configurations are used to create N named HttpClients, one per endpoint. I've used this example to create an EF Core provider that loads the endpoint settings.

This allows validation of the settings when the application starts too, which can be a significant benefit. Without it, the application wouldn't know something's wrong until the first time a specific HttpClient was requested.

Upvotes: 3

Related Questions