Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);
like image 771
Iskander Raimbaev Avatar asked Mar 18 '19 13:03

Iskander Raimbaev


2 Answers

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.

like image 133
Iskander Raimbaev Avatar answered Oct 20 '22 13:10

Iskander Raimbaev


I found a solution.

I'm in ASP.NET Core 3.1.

My handler class :

public class GetProductsListQueryHandler : IRequestHandler<GetProductsListQueryModel, IEnumerable<Product>>
{
    private readonly HttpClient _httpClient;

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

You need to implement your HttpClient in your Startup like this :

services.AddHttpClient<IRequestHandler<GetProductsListQueryModel,IEnumerable<Product>>, GetProductsListQueryHandler>();

And it works! ;)

like image 1
pdouelle Avatar answered Oct 20 '22 11:10

pdouelle