Search code examples
c#dependency-injectionautofac

Autofac and IHttpClientFactory: Cannot resolve parameter 'System.Net.Http.HttpClient httpClient'


I'm building a console app and I decide to use Autofac following the example detailed here.

So I:

Registered the Autofac Service Provider

...
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
...

Registerd the IHttpClientFactory:

containerBuilder
    .Register(ctx => ctx.Resolve<IHttpClientFactory>().CreateClient())
    .As<HttpClient>();

Registered all the other services, in particular:

containerBuilder.RegisterType<UpdaterServiceClient>().As<IUpdaterServiceClient>();

The UpdaterServiceClient has a constructor like this:

public UpdaterServiceClient(SBMOptions sbmOptions, IHttpClientFactory httpClientFactory, ILogger<UpdaterServiceClient> logger)

The exception I obtain is:

Type: Autofac.Core.DependencyResolutionException Message: An exception was thrown while activating UpdaterServiceClient. Type: Autofac.Core.DependencyResolutionException Message: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'UpdaterServiceClient' can be invoked with the available services and parameters: Cannot resolve parameter 'System.Net.Http.IHttpClientFactory httpClientFactory' of constructor 'Void .ctor(SBMOptions, System.Net.Http.IHttpClientFactory, Microsoft.Extensions.Logging.ILogger`1[UpdaterServiceClient])'.

Any suggestions as to what may be causing the issue


Solution

  • The example in the article is wrong. There seems to be a misconception as to what

    containerBuilder
        .Register(ctx => ctx.Resolve<IHttpClientFactory>().CreateClient())
        .As<HttpClient>();
    

    is actually doing.

    It appears to be registering HttpClient and not IHttpClientFactory which would explain why the container has no knowledge of the type.

    I suggest refactoring to add/configure the factory via the default extension and then using the 3rd party service provider.

    Based on the article, it would look like this.

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) => {
                services.AddHttpClient(); //<-- ADD IHttpClientFactory AND RELATED SERVICES
            })
            .UseServiceProviderFactory(new AutofacServiceProviderFactory())
            .ConfigureWebHostDefaults(webBuilder => {
                webBuilder.UseStartup<Startup>();
            });
    

    When UseServiceProviderFactory is invoked above, everything that was already added to the default ServiceCollection will be populated over to the Autofac Service Provider