'ASP.NET Core MediatR error: Register your handlers with the container
I have a .Net Core app where i use the .AddMediatR
extension to register the assembly for my commands and handlers following a CQRS approach.
In ConfigureServices in Startup.cs i have used the extension method from the official package MediatR.Extensions.Microsoft.DependencyInjection
with the following parameter:
services.AddMediatR(typeof(AddEducationCommand).GetTypeInfo().Assembly);
The command and commandhandler classes are as follow:
AddEducationCommand.cs
public class AddEducationCommand : IRequest<bool>
{
[DataMember]
public int UniversityId { get; set; }
[DataMember]
public int FacultyId { get; set; }
[DataMember]
public string Name { get; set; }
}
AddEducationCommandHandler.cs
public class AddEducationCommandHandler : IRequestHandler<AddEducationCommand, bool>
{
private readonly IUniversityRepository _repository;
public AddEducationCommandHandler(IUniversityRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(AddEducationCommand command, CancellationToken cancellationToken)
{
var university = await _repository.GetAsync(command.UniversityId);
university.Faculties
.FirstOrDefault(f => f.Id == command.FacultyId)
.CreateEducation(command.Name);
return await _repository.UnitOfWork.SaveEntitiesAsync();
}
}
When i run the REST endpoint that executes a simple await _mediator.Send(command);
code, i get the following error from my log:
Error constructing handler for request of type MediatR.IRequestHandler`2[UniversityService.Application.Commands.AddEducationCommand,System.Boolean]. Register your handlers withthe container. See the samples in GitHub for examples.
I tried to look through the official examples from the docs without any luck. Does anyone know how i configure MediatR to work properly? Thanks in advance.
Solution 1:[1]
I have met the same issue.
The problem is that this line code
services.AddMediatR(typeof(AddEducationCommand).GetTypeInfo().Assembly);
handles all the MediatR IRequest and IRequestHandlers.
but you created an IRepository interface and its implementation class which can't be handled by that MediatR.Extensions.Microsoft.DependencyInjection
so keep all your changes but add this - manually register this like
services.AddScoped(typeof(IUniversityRepository), typeof(UniversitySqlServerRepository));
then issue resolved.
Solution 2:[2]
I went through the same problem and searched for hours but nothing found because this error is a very generic error. Apparently it looks like a MediatR problem but very often, it is NOT the case.
How I went to this conclusion?
To get the original exception, I opened Event Viewer application, which exists by default in windows
In the custom Views > Summary Page Events
I found some errors, which corresponded to my application. In my case Errors was something like this:
An error occured during migration
Exception:
System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString')
at Microsoft.EntityFrameworkCore.Utilities.Check.NotEmpty(String value, String parameterName)
at Microsoft.EntityFrameworkCore.MySqlDbContextOptionsExtensions.UseMySql(DbContextOptionsBuilder optionsBuilder, String connectionString, Action`1 mySqlOptionsAction)
As the error says, connectionString
was empty. Ultimately I found out that when I was publishing my application to get the dlls, appsettings.json
was not in the published folder, due to which connectionString
was not found, which is why migration failed. and ultimately, app crashed with a very generic error:
Error constructing handler for request of type MediatR.IRequestHandler.
Register your handlers with the container. See the samples in GitHub for examples
Solution 3:[3]
I had the same problem and in my case when I was registering the dependencies that certain handler needed after I was calling services.AddMediatR()
was the actual issue, after I started registering my dependencies before registering Mediator everything works fine.
I'm using dot net core 2.2 with the default DI container and MediatR 6.0.0.
Solution 4:[4]
For me, none of the other solutions worked unfortunately as I had already registered everything. The solution for me was adding the following line to my program.cs:
.UseDefaultServiceProvider(options => options.ValidateScopes = false);
So the CreateHostBuilder
method will be changed to:
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).UseDefaultServiceProvider(options =>
options.ValidateScopes = false); // needed for mediatr DI
Actually that is something to do with "scoped service", you may find this answer also related.
Solution 5:[5]
I solved using this alternative
services.AddMediatR(AppDomain.CurrentDomain.GetAssemblies());
Solution 6:[6]
Maybe the issue is that your Handlers are in a separate assembly, if they are, you need to register that assembly name in Startup.cs.
public void ConfigureServices(IServiceCollection services){
var assembly = AppDomain.CurrentDomain.Load("HandlersDomain");
services.AddMediatR(assembly);
}
"HandlersDomain" is the name of the assembly where all your Handlers are stored.
Solution 7:[7]
I had this issue today and my solution and point of note is, if you are going to do this :
services.AddMediatR(Assembly.GetExecutingAssembly());
kindly ensure that the assembly being gotten is the same assembly as your Handlers. In my case, the Handlers were in a different assembly (or project as you may call it).
Solution 8:[8]
In my case, I had forgotten to register something in my Startup. Like the repository that I was attempting to have implemented via a controller. This was missing in method ConfigureServices
of Startup.cs
:
services.AddScoped<IDemoRepository, DemoRepository>();
Solution 9:[9]
Mine turned out to be a bad name attribute in the controller. It was the word "clients" which was already in the url. Changed the name attribute to "clientlist" and it started working.
Solution 10:[10]
In my case the stack trace showed why the problem happened:
System.InvalidOperationException: Error constructing handler for request of type
MediatR.IRequestHandler`2[XXX.Core.Auth.Refresh.Request,XXXX.Core.Auth.Response].
Register your handlers with the container. See the samples in GitHub for examples.
---> MySqlConnector.MySqlException (0x80004005): Access denied for user 'sqluser'@'localhost' (using password: YES)
My database didn't have the user specified in connection string set up. Fixed by adding the user to the database.
Solution 11:[11]
I am also doing Clean Architecture and CQRS per https://github.com/jasontaylordev/NorthwindTraders
I coded the following:
public class MyClassUpdateCommandHandler : IRequest<MyClass>
but is should have been:
public class MyClassUpdateCommandHandler : IRequestHandler<MyClassUpdateCommand, MyClass>
A more complete example is the following:
public class MyClassUpdateCommand : IRequest<MyClass>
{
public string Id { get; set; }
...
//
public MyClassUpdateCommand()
{
Id = "";
...
}
}
//
public class MyClassUpdateCommandHandler : IRequestHandler<MyClassUpdateCommand, MyClass>
{
private ApplicationDbContext _context;
public MyClassUpdateCommandHandler(ApplicationDbContext context, IMediator mediator)
{
_context = context;
}
//
public async Task<MyClass> Handle(MyClassUpdateCommand request, CancellationToken cancellationToken)
{
...
return _entity;
}
//
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow