首页 > 解决方案 > 如何在 DI 中注册自定义 UserManager 等 - ASP.NET Core 2.1

问题描述

我需要创建自己的类来处理 EF Core 2.1 中的身份。我有以下那些,但是当想要 inbocar 控制器的方法时,我收到以下错误

尝试激活“Sample.API.Models.Identity.Managers.ApplicationUserManager”时无法解决“Sample.API.Models.Identity.Stores.ApplicationUserStore”类型的服务。

public void ConfigureServices(IServiceCollection servicesCollection)
{
    servicesCollection.AddDbContext<MyIndentityContext>(currentOptions =>
        currentOptions.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    servicesCollection.AddIdentity<ApplicationUser, ApplicationRole>()
        .AddEntityFrameworkStores<MyIndentityContext>()
        .AddRoleStore<ApplicationRoleStore>()
        .AddUserStore<ApplicationUserStore>()
        .AddUserManager<ApplicationUserManager>()
        .AddRoleManager<ApplicationRoleManager>()
        .AddSignInManager<ApplicationSignInManager>()
        .AddDefaultTokenProviders();

        servicesCollection.AddTransient<UserManager<ApplicationUser>, ApplicationUserManager>();
        servicesCollection.AddTransient<SignInManager<ApplicationUser>, ApplicationSignInManager>();
        servicesCollection.AddTransient<RoleManager<ApplicationRole>, ApplicationRoleManager>();
        servicesCollection.AddTransient<IUserStore<ApplicationUser>, ApplicationUserStore>();
        servicesCollection.AddTransient<IRoleStore<ApplicationRole>, ApplicationRoleStore>();

        ...

        ...

        ...
}

public class MyIndentityContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>
{
    private readonly IConfiguration _configuration;

    private readonly IHttpContextAccessor _httpContextAccessor;

    public MyIndentityContext(DbContextOptions dbContextOptions, IHttpContextAccessor httpContextAccessor,
        IConfiguration configuration)
        : base(dbContextOptions)
    {
        _configuration = configuration;
        _httpContextAccessor = httpContextAccessor;
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.HasDefaultSchema("Sample.API");
    }

}

public class ApplicationRoleManager : RoleManager<ApplicationRole>
{
    public ApplicationRoleManager(ApplicationRoleStore roleStore,
        IEnumerable<IRoleValidator<ApplicationRole>> roleValidators, ILookupNormalizer keyNormalizer,
        IdentityErrorDescriber errors, ILogger<ApplicationRoleManager> logger) : base(roleStore,
        roleValidators,
        keyNormalizer, errors, logger)
    {
    }
}

public class ApplicationSignInManager : SignInManager<ApplicationUser>
{
    public ApplicationSignInManager(ApplicationUserManager userManager, IHttpContextAccessor contextAccessor,
        IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory, IOptions<IdentityOptions> optionsAccessor,
        ILogger<ApplicationSignInManager> logger, IAuthenticationSchemeProvider schemes) : base(userManager,
        contextAccessor, claimsFactory, optionsAccessor, logger, schemes)
    {
    }
}

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    public ApplicationUserManager(ApplicationUserStore userStore, IOptions<IdentityOptions> optionsAccessor,
        IPasswordHasher<ApplicationUser> passwordHasher,
        IEnumerable<IUserValidator<ApplicationUser>> userValidators,
        IEnumerable<IPasswordValidator<ApplicationUser>> passwordValidators, ILookupNormalizer keyNormalizer,
        IdentityErrorDescriber errors, IServiceProvider services, ILogger<ApplicationUserManager> logger) :
        base(userStore, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors,
            services, logger)
    {
    }
}

public class ApplicationRoleStore : RoleStore<ApplicationRole, MyIndentityContext>
{
    public ApplicationRoleStore(MyIndentityContext dbContext, IdentityErrorDescriber identityErrorDescriber)
        : base(dbContext, identityErrorDescriber)
    {}
}

public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, MyIndentityContext, string>
{
    public ApplicationUserStore(MyIndentityContext dbContext, IdentityErrorDescriber identityErrorDescriber)
        : base(dbContext, identityErrorDescriber)
    {}

}

public class ApplicationUser : IdentityUser {}

public class ApplicationRole : IdentityRole
{
    public ApplicationRole() { }

    public ApplicationRole(string roleName) : base(roleName) { }

    public ApplicationRole(string roleName, string roleDescription) : base(roleName)
    {
        Description = roleDescription;
    }

}

[Authorize]
[ApiController]
[Route("api/[controller]")]
[EnableCors(CORS.AllowSpecificOrigins)]

public class UserController : BaseController
{
    private readonly ApplicationUserManager _applicationUserManager;

    public UserController(ApplicationUserManager applicationUserManager)
    {
        _applicationUserManager = applicationUserManager;
    }

     // GET: api/User/5
    [HttpGet("{id}")]
    public async Task<UserDTO> Get(int id)
    {

        var currentuser = await _applicationUserManager.FindByNameAsync("NAME");

        return ...;

    }

}

编辑:

在按照用户“Camilo Terevinto”的建议进行操作后,我成功了,但我还必须更改所有管理器的构造函数。例如,我必须通过IRoleStore roleStore更改ApplicationRoleStore roleStore

标签: c#asp.net-coreasp.net-core-2.1

解决方案


使用依赖注入时,具有依赖关系的类不要求实现,它们要求契约。

这:

private readonly ApplicationUserManager _applicationUserManager;

public UserController(ApplicationUserManager applicationUserManager)
{
    _applicationUserManager = applicationUserManager;
}

应该:

private readonly UserManager<ApplicationUser> _applicationUserManager;

public UserController(UserManager<ApplicationUser> applicationUserManager)
{
    _applicationUserManager = applicationUserManager;
}

另外,请注意您不需要任何这些行,这些行已经由之前的调用.AddIdentity及其选项添加。

servicesCollection.AddTransient<UserManager<ApplicationUser>, ApplicationUserManager>();
servicesCollection.AddTransient<SignInManager<ApplicationUser>, ApplicationSignInManager>();
servicesCollection.AddTransient<RoleManager<ApplicationRole>, ApplicationRoleManager>();
servicesCollection.AddTransient<IUserStore<ApplicationUser>, ApplicationUserStore>();
servicesCollection.AddTransient<IRoleStore<ApplicationRole>, ApplicationRoleStore>();

推荐阅读