Search code examples
c#asp.net-core-2.0mediatr

Cannot inject HttpClient in typed client while using with IMediatR library


According to examples provided by ASP.NET Core 2.2 documentation in MSDN, it is possible to inject HttpClient to a typed clients (service-classes) by adding the following line to Startup.cs:

// Startup.cs
services.AddHttpClient<GitHubService>();

From controller class it will look like (from now I will use GitHub as a simplification for a domain model):

// GitHubController.cs
public class GitHubController : Controller
{
    private readonly GitHubService _service;
    public GitHubController(GitHubService service)
    {
        _service = service;
    }
}

However, I use MediatR library in my project, so my project structure looks a bit different. I have 2 projects - GitHubFun.Api, GitHubFun.Core - ASP.NET Core 2.2 API project and .NET Core 2.2 class library respectively.

My controller:

// GitHubController.cs
public class GitHubController : Controller
{
    private readonly IMediator _mediator;
    public GitHubController(IMediator mediator)
    {
        _mediator= mediator;
    }

    public async Task<IActionResult> GetGitHubRepositoryInfo(
        GetGitHubRepositoryCommand command)
    {
         _mediator.Send(command);
    }
}

And my handler class:

// GetGitHubRepositoryHandler.cs
public class GetGitHubRepositoryHandler : 
    IRequestHandler<GetGitHubRepositoryCommand , GetGitHubRepositoryCommandResult>
{
    private HttpClient _httpClient;

    public GetGitHubRepositoryHandler(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }
}

When I make HTTP request and call an API method, it successfully injects IMediator, but throws an exception on _mediator.Send(command) line.

Exception body:

System.InvalidOperationException: Error constructing handler for request of type MediatR.IRequestHandler`2[IDocs.CryptoServer.Core.Commands.ExtractX509Command,IDocs.CryptoServer.Core.Commands.ExtractX509CommandResult]. Register your handlers with the container. See the samples in GitHub for examples. ---> System.InvalidOperationException: Unable to resolve service for type 'System.Net.Http.HttpClient' while attempting to activate 'IDocs.CryptoServer.Core.Handlers.ExtractX509CommandHandler'

(ExtractX509CommandHandler - is just a real domain model, instead of GetGitHubRepositoryHandler).

It seems that ASP.NET Core DI cannot resolve DI and inject HttpClient to handler.

My Startup.cs has the following lines:

services.AddHttpClient<ExtractX509CommandHandler>();
services.AddMediatR(
       typeof(Startup).Assembly, 
       typeof(ExtractX509CommandHandler).Assembly);

Solution

  • I found a solution. For some reasons, in this case we need to pass IHttpClientFactory from Microsoft.Extensions.Http.dll instead of HttpClient to handler class. I just changed one line, it was:

    public GetGitHubRepositoryHandler(HttpClient httpClient)
    

    and now:

    public GetGitHubRepositoryHandler(IHttpClientFactory httpClientFactory)
    

    and now it works as it should. I don't know why it works, so it will be perfect, if someone could explain what is the difference between injecting IHttpClientFactory and HttpClient to the class.