首页 > 解决方案 > 使用多个身份用户时,Identity.UserManager 类型没有服务

问题描述

我的设置

目前,我有两个继承自的模型,继承ApplicationUserIdentityUser. 用户类别是:

public abstract class ApplicationUser : IdentityUser
{
    [PersonalData]
    public string FirstName { get; set; }

    [PersonalData]
    public string LastName { get; set; }

    [NotMapped]
    public string FullName => $"{FirstName} {LastName}";
}

public class StudentUser : ApplicationUser
{
    [PersonalData]
    [Required]
    public string StudentNumber { get; set; }

    // A user belongs to one group
    public Group Group { get; set; }
}

public class EmployeeUser : ApplicationUser { }

ApplicationUser包含共享属性,例如名字和姓氏。两者都有自己属性和关系StudentUser。此结构遵循按层次结构表 (TPH)继承。EmployeeUser

理想情况下,我想遵循Table Per Type (TPT)继承,因为 SQL 结构更好。ASP.NET Core 仅原生支持 TPH,这就是我遵循 TPT 方法的原因。

问题

我在以下位置添加了身份服务Startup.cs

services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

当我调用UserManager<StudentUser>orUserManager<EmployeeUser>时,我收到以下错误:

没有注册类型“Microsoft.AspNetCore.Identity.UserManager`1[ClassroomMonitor.Models.StudentUser]”的服务。

我的问题

不幸的是,我找不到太多关于这个错误与这个实现的结合。

(甚至)有可能让它以这种方式工作吗?

欢迎任何帮助或想法。

更新 1

手动添加StudentUserorEmployeeUser作为范围服务似乎不起作用(作为第一个答案提到)。

services.AddScoped<UserManager<ApplicationUser>, UserManager<ApplicationUser>>();
// or..
services.AddScoped<UserManager<ApplicationUser>>();

这会引发以下错误:

InvalidOperationException:无法解析“Microsoft.AspNetCore.Identity.IUserStore1[ClassroomMonitor.Models.StudentUser]”类型的服务

更新 2

这是一个要点,可以让您更好地了解项目结构:

标签: c#.net-coreentity-framework-coreroles

解决方案


理想情况下,您会为派生用户类型调用与基本用户类型相同的身份设置。

不幸的是AddIdentity,方法包含一些阻止多次使用它的代码。

相反,您可以使用AddIdentityCore. 角色服务已经被 注册了AddIdentity,唯一的区别是AddIdentityCore注册了UserClaimsPrincipalFactory<TUser>,所以为了匹配AddIdentity设置,需要用UserClaimsPrincipalFactory<TUser, TRole>viaAddClaimsPrincipalFactory方法替换它。

代码看起来像这样:

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders()
    .AddDefaultUI();

services.AddIdentityCore<StudentUser>()
    .AddRoles<IdentityRole>()
    .AddClaimsPrincipalFactory<UserClaimsPrincipalFactory<StudentUser, IdentityRole>>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders()
    .AddDefaultUI();

services.AddIdentityCore<EmployeeUser>()
    .AddRoles<IdentityRole>()
    .AddClaimsPrincipalFactory<UserClaimsPrincipalFactory<EmployeeUser, IdentityRole>>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders()
    .AddDefaultUI();

当然,您可以在自定义扩展方法中移动公共部分。

更新:虽然角色服务已经配置好了,你仍然需要调用AddRoles才能正确设置 的Role属性IndentityBuilder,然后由AddEntityFrameworkStores.


推荐阅读