1
votes

I am building ASP.Net Core App depending on this clean architecture example which is using MediatR to execute commands. And i want to use ASP.Net Core Identity in my app, so in my CreateUserCommandHandler i want to use UserManager to add new user, but when i add UserManager to Command contractor MediatR unable to create the handler and fail with this exception:

System.InvalidOperationException: Error constructing handler for request of type MediatR.IRequestHandler`2[GoGYM.Application.Identity.Commands.CreateUser.CreateUserCommand,MediatR.Unit]. Register your handlers with the container. See the samples in GitHub for examples. ---> System.InvalidOperationException: Unable to resolve service for type 'GoGYM.Persistence.GoGYMDbContext' while attempting to activate 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`9[GoGYM.Domain.Entities.ApplicationUser,GoGYM.Domain.Entities.ApplicationRole,GoGYM.Persistence.GoGYMDbContext,System.String,Microsoft.AspNetCore.Identity.IdentityUserClaim`1[System.String],Microsoft.AspNetCore.Identity.IdentityUserRole`1[System.String],Microsoft.AspNetCore.Identity.IdentityUserLogin`1[System.String],Microsoft.AspNetCore.Identity.IdentityUserToken`1[System.String],Microsoft.AspNetCore.Identity.IdentityRoleClaim`1[System.String]]'.

In Configure services i register my DBContext and MediatR like this:

// Add AutoMapper
        services.AddAutoMapper(new Assembly[] { typeof(AutoMapperProfile).GetTypeInfo().Assembly });
        // Add MediatR
        services.AddMediatR(typeof(GetUsersListQueryHandler).GetTypeInfo().Assembly);
        // Add DbContext using SQL Server Provider
        services.AddDbContext<IGoGYMDbContext, GoGYMDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("NorthwindDatabase")));

        services.AddIdentity<ApplicationUser, ApplicationRole>()
            .AddDefaultTokenProviders()
             .AddEntityFrameworkStores<GoGYMDbContext>();
        services.AddMvc();
....

And this my command handler code:

public class CreateUserCommandHandler : IRequestHandler<CreateUserCommand, Unit>
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly IGoGYMDbContext _context;

    public CreateUserCommandHandler(IGoGYMDbContext context, UserManager<ApplicationUser> userManager)
    {
        _context = context;
        _userManager = userManager;
    }
    public Task<Unit> Handle(CreateUserCommand request, CancellationToken cancellationToken)
    {
        throw new NotImplementedException();
    }
}

And my controller

[HttpPost]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesDefaultResponseType]
    public async Task<IActionResult> Create(string values)
    {
        await Mediator.Send(new CreateUserCommand(values));

        return NoContent();
    }

I have tried a lot of things and nothing work, only if i remove UserManager from command handler it gets executed then.

1
Do CreateUserCommandHandler and GetUsersListQueryHandler live in the same assembly?ColinM
Yes in the same assembly and GetUsersListQueryHandler works fine also CreateUserCommandHandler works fine if i removed UserManagerAlaaL

1 Answers

4
votes

You register IGoGYMDbContext with DI but pass in GoGYMDbContext to AddEntityFrameworkStores. GoGYMDbContext isn't registered with DI, so it can't be resolved when requested by the ASP.NET Core Identity framework.

The following changes allow you to register both the interface and the implementation, but using the same implementation instance whether requested via the interface or the implementation:

  1. Remove the interface from the call to AddDbContext:

    services.AddDbContext<GoGYMDbContext>(...);
    
  2. Add a passthrough from the interface to the GoGYMDbContext implementation:

    services.AddScoped<IGoGYMDbContext>(sp => sp.GetRequiredService<GoGYMDbContext>());