MediatR error: Register your handlers with the container

18k views Asked by At

I have a .Net Core app where i use the .AddMediatR extension to register the assembly for my commands and handlers

In ConfigureServices in Startup.cs i have used the extension method from the official package MediatR.Extensions.Microsoft.DependencyInjection with the following parameter:

startup.cs

 services.AddBLL();

DependencyInjection.cs

public static IServiceCollection AddBLL(this IServiceCollection services)
    {
        services.AddAutoMapper(Assembly.GetExecutingAssembly());
        services.AddMediatR(Assembly.GetExecutingAssembly());
        services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPerformanceBehaviour<,>));
        services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestValidationBehavior<,>));

        return services;
    }

The commandhandler class are as follow: ListEpostaHesaplariHandler.cs

public class ListEpostaHesaplariRequest : IRequest<ResultDataDto<List<ListEpostaHesaplariDto>>>
{
    public FiltreEpostaHesaplariDto Model { get; set; }
}

public class ListEpostaHesaplariHandler : IRequestHandler<ListEpostaHesaplariRequest, ResultDataDto<List<ListEpostaHesaplariDto>>>
{
    private readonly IBaseDbContext _context;
    private readonly IMapper _mapper;

    public ListEpostaHesaplariHandler(IBaseDbContext context, IMapper mapper)
    {
        _context = context;
        _mapper = mapper;
    }

    public async Task<ResultDataDto<List<ListEpostaHesaplariDto>>> Handle(ListEpostaHesaplariRequest request, CancellationToken cancellationToken)
    {
        await Task.Delay(1);

        var resultDataDto = new ResultDataDto<List<ListEpostaHesaplariDto>>() { Status = ResultStatus.Success };

        try
        {
            var foo = _context.EpostaHesaplari;

            var filtreliEpostaHesaplari = Filtre(request.Model, foo);

            var epostaHesaplariDto = _mapper.Map<List<ListEpostaHesaplariDto>>(filtreliEpostaHesaplari);

            resultDataDto.Result = epostaHesaplariDto;
        }
        catch (Exception ex)
        {
            resultDataDto.Status = ResultStatus.Error;
            resultDataDto.AddError(ex.Message);
        }

        return resultDataDto;
    }

This is the Controller I used the MediatR

BaseController.cs

  public abstract class BaseController : Controller
{
    private IMediator _mediator;
    public static int? birimIDD;
    protected IMediator Mediator
    {
        get
        {
            return _mediator ??= HttpContext.RequestServices.GetService<IMediator>();
        }
    }
}

HomeController.cs

[HttpPost]
    public async Task<IActionResult> MailGonderAsync()
    {

        FiltreEpostaHesaplariDto filtre = new FiltreEpostaHesaplariDto();
        filtre.Durum = true;
        var req = new ListEpostaHesaplariRequest() { Model = filtre };
        var response = await Mediator.Send(req);
    }

no problem so far await Mediator.Send(req); this response is coming successfully

the problem starts from here

send.cs (in class business logic layer )

public class EmailSend : IEmailSingleSender
{
    private readonly IMediator _mediator;

    public EmailSend(IMediator mediator)
    {
        _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));

    }

    public async Task Send(EmailParamsDto emailParamsDto)
    {
        try
        {
            FiltreEpostaHesaplariDto filtre = new FiltreEpostaHesaplariDto();
            filtre.Durum = true;
            var req = new ListEpostaHesaplariRequest() { Model = filtre };
            var response = await _mediator.Send(req);

            SmtpClient smtpClient = new SmtpClient();
            smtpClient.Port = _emailSetting.Port;
            smtpClient.Host = _emailSetting.Server;
            smtpClient.EnableSsl = _emailSetting.UseSsl;
            NetworkCredential networkCredential = new NetworkCredential();
            networkCredential.UserName = _emailSetting.UserName;
            networkCredential.Password = _emailSetting.Password;
            smtpClient.Credentials = networkCredential;
            MailMessage mail = new MailMessage();
            mail.IsBodyHtml = _emailSetting.IsHtml;
            mail.From = new MailAddress(_emailSetting.UserName, emailParamsDto.Subject);
            mail.To.Add(new MailAddress(emailParamsDto.Receiver));
            //mail.CC.Add(_emailSetting.AdminMail);
            mail.Body = emailParamsDto.Body;
            mail.Subject = emailParamsDto.Subject;
            mail.Priority = emailParamsDto.MailPriority;

            await smtpClient.SendMailAsync(mail);
        }
        catch (Exception ex)
        {

            throw ex;
        }
    }
}

When this line, in the Send method, executes I get the exception:

var response = await _mediator.Send(req); 

Error constructing handler for request of type MediatR.IRequestHandler2[IUC.BaseApplication.BLL.Handlers.Yonetim.EpostaHesaplariHandlers.ListEpostaHesaplariRequest,IUC.BaseApplication.COMMON.Models.ResultDataDto1[System.Collections.Generic.List`1[IUC.BaseApplication.BLL.Models.Yonetim.EpostaHesaplariDto.ListEpostaHesaplariDto]]]. Register your handlers with the container. See the samples in GitHub for examples.

5

There are 5 answers

0
MestreDosMagros On
services.AddMediatR(Assembly.GetExecutingAssembly());

All your handlers and commands are in this assembly you passed?

0
Aftab Ahmed Kalhoro On

If MediateR handler has any object injected through DI & that DI object's constructor is throwing exception, you will encounter also this error. For example, MediateR handler has IRepository injected and object of IRepository constructor is trying to open database connection, but exception is thrown you'll encounter Error constructing handler for request of type MediatR.

    public class MyHandler : IRequestHandler<Command, Result>
    {

        private readonly IRepository _myRepo;
        private readonly IMapper _mapper;

        public MyHandler(IRepository myRepo, IMapper mapper)
        {

            _myRepo = myRepo;
            _mapper = mapper;
        }
    }

And Repository code is

public class MyRepository : IRepository
{
    private IDbConnection _connection;
    private readonly IConfiguration _configuration;

    public MyRepository(IConfiguration configuration)
    {
            _configuration = configuration;
            string connStr = _configuration.GetConnectionString("DefaultConnection")
            _connection = new OracleConnection(connStr);

            _connection.Open(); // if this line throws exception
    }
}

_connection.Open(); will cause the Error constructing handler for request of type MediatR. if exception is thrown while opening the connection

0
Ivan  Panchenko On

The problem might be because "No parameterless constructor defined" for e.g. MappingProfiles class inherited from Profile class. And it must be public, not protected. You might not see this exception if your custom middleware hides inner exceptions.

2
kargarf On
builder.Services.AddMediatR(AppDomain.CurrentDomain.GetAssemblies());

MediatR Service Registration in Dotnet 6 in program files.

0
arpit rai On
  public class TestQueryHandler : IRequestHandler<TestQuery, int>
{
    public Task<int> Handle(TestQuery request, CancellationToken cancellationToken)
    {
        return Task.FromResult(10);
    }
}
Assembly myTestQueryHandlerAssebmly = typeof(TestQueryHandler).Assembly;  //Reg my Handler
builder.Services.AddTransient<TestQueryHandler, TestQueryHandler>();
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(myTestQueryHandlerAssebmly));