Search code examples
c#dependency-injection.net-corehttpclientautofac

How to register typed httpClient service with autofac?


I'm creating MVC web application which calls an api using .net core 2.2 using separate HttpClients to call each controller (same api).

Ex:

  • For user controller actions : UserService (httpclient)
  • For post controller actions : PostService (httpclient)

In startup.cs I use DI as:

services.AddHttpClient<IUserService, UserService>();
services.AddHttpClient<IPostService, PostService>();

In my handler :

public class CommandHandler : IRequestHandler<Command, BaseResponse>
{
    private readonly IUserService _userService;

    public CommandHandler(IUserService userService)
    {
        _userService = userService;
    }

    public Task<BaseResponse> Handle(Command request, CancellationToken cancellationToken)
    {
        throw new System.NotImplementedException();
    }
}

But when invoking command handler I get this error:

None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'xxx.Application.Services.Users.UserService' can be invoked with the available services and parameters: Cannot resolve parameter 'System.Net.Http.HttpClient httpClient' of constructor 'Void .ctor(System.Net.Http.HttpClient, xxx.Application.Configurations.IApplicationConfigurations, Microsoft.Extensions.Logging.ILogger`1[xxx.Application.Services.Users.UserService])'.

But I've registered services in autofac module:

public class ServiceModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterAssemblyTypes(typeof(ServiceModule).Assembly)
                .Where(t => t.Namespace.StartsWith("xxx.Application.Services"))
                .AsImplementedInterfaces().InstancePerLifetimeScope();
    }
}

Here is my UserService class constructor:

public UserService (HttpClient httpClient, IApplicationConfigurations applicationConfig, ILogger<UserService> logger)
{
    _httpClient = httpClient;
    _applicationConfig = applicationConfig;
    _logger = logger;

    _remoteServiceBaseUrl = $"{_applicationConfig.WebApiBaseUrl}";
}

I have two questions:

  1. What does the above error mean?
  2. Is it good practice to use separate httpclients for different controllers in api?

Solution

  • As per the https://autofac.readthedocs.io/en/latest/integration/netcore.html#quick-start page, the simplest, and most correct method is this:

    // Generate a ServiceCollection to directly add elements to.
    var serviceCollection = new ServiceCollection();
    
    // Add the HTTP Client as per the extension.
    serviceCollection.AddHttpClient();
    serviceCollection.AddHttpClient<IUserService, UserService>();
    serviceCollection.AddHttpClient<IPostService, PostService>();
    
    // Build the ContainerBuilder.
    var containerBuilder = new ContainerBuilder();
    
    // Populate the builder from the ServiceCollection.
    containerBuilder.Populate(serviceCollection);
    
    // Continue with the AutoFac registrations after this point.