C# 使用多个标识用户时,类型Identity.UserManager没有服务

C# 使用多个标识用户时,类型Identity.UserManager没有服务,c#,.net-core,entity-framework-core,roles,C#,.net Core,Entity Framework Core,Roles,我的设置 目前,我有两个模型继承自ApplicationUser,它们继承了IdentityUser。用户类别包括: public abstract class ApplicationUser : IdentityUser { [PersonalData] public string FirstName { get; set; } [PersonalData] public string LastName { get; set; } [NotMappe

我的设置

目前,我有两个模型继承自
ApplicationUser
,它们继承了
IdentityUser
。用户类别包括:

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
EmployeeUser
都有自己的属性和关系。此结构遵循继承

理想情况下,我希望遵循继承,因为SQL结构更好。ASP.NET核心仅在本机上支持TPH,因此我采用TPT方法

问题

我在
Startup.cs
中添加了标识服务:

services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
这会引发以下错误:

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

更新2


下面是一个可以让您更好地了解项目结构的示例:

您缺少它的注册DI

services.AddScoped<UserManager<AppUser>, UserManager<AppUser>>()
services.AddScoped()

StudentUser和EmployeeUser与fresh项目中测试的类似:

dotnet新mvc--身份验证个人

Startup.cshtml

services.AddDefaultIdentity<User>()
    .AddEntityFrameworkStores<ApplicationDbContext>();
这可能是您的问题:

_LoginPartial.cshtml

@inject SignInManager<User> SignInManager
@inject UserManager<User> UserManager
@inject SignInManager<User2> SignInManager
@inject UserManager<User2> UserManager
_LoginPartial.cshtml

@inject SignInManager<User> SignInManager
@inject UserManager<User> UserManager
@inject SignInManager<User2> SignInManager
@inject UserManager<User2> UserManager
@inject-SignInManager-SignInManager
@注入用户管理器用户管理器

理想情况下,您可以为派生用户类型调用与基本用户类型相同的标识设置

不幸的是,该方法包含一些代码,无法多次使用它

相反,你可以使用。角色服务已经由
附加属性
注册,唯一的区别是
附加属性核心
注册了
UserClaimsPrincipalFactory
,因此为了匹配
附加属性
设置,需要通过方法将其替换为
UserClaimsPrincipalFactory

代码如下所示:

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();
services.AddIdentity()
.AddEntityFrameworkStores()
.AddDefaultTokenProviders()
.AddDefaultUI();
services.AddIdentityCore()
.AddRoles()
.AddClaimsPrincipalFactory()
.AddEntityFrameworkStores()
.AddDefaultTokenProviders()
.AddDefaultUI();
services.AddIdentityCore()
.AddRoles()
.AddClaimsPrincipalFactory()
.AddEntityFrameworkStores()
.AddDefaultTokenProviders()
.AddDefaultUI();
当然,您可以在自定义扩展方法中移动公共部分


更新:虽然已经配置了角色服务,但是您仍然需要调用
AddRoles
,以便正确设置
IndentityBuilder
role
属性,该属性随后被
AddEntityFrameworkStores
使用。您无法为不同的用户类型添加作用域,实际上,您不应该有许多不同的类型是从IdentityUser派生的,因为这意味着您可能会到处使用不正确的类型,或者数据库中有多个不同的用户表

您应该真正构建数据,使其具有一个由员工实体(一个单独的实体)或学生实体(同样是一个单独的实体)引用的
ApplicationUser
。 这里更多的是设计问题,而不是代码问题

ASPIdentity将在您添加身份时插入
用户管理器
,因此添加更多用户管理器将无法按预期工作

答案 您必须为每种类型的用户创建不同的实体,1个用于学生,1个用于员工,等等。这些实体都将具有用户id的外键,这将使您能够添加多种类型的用户,而无需为每种用户类型创建不同的表

然后,当您注册
addIdentity
时,您可以注册
ApplicationUser
(目前的情况),然后注入
UserManager
,这将获得用户类型。

如果core>=3.0

services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<WorldContext>();
services.AddIdentity()
.AddEntityFrameworkStores();

这会产生以下错误:
InvalidOperationException:无法解析类型为“Microsoft.AspNetCore.Identity.IUserStore”的服务,同时尝试激活“Microsoft.AspNetCore.Identity.UserManager”
1[ClassroomMonitor.Models.StudentUser]“.
我也必须将其更改为单独的行。您是否注册了足够的
服务。AddScoped()
服务。AddScoped()
服务。AddScoped()
是的,但这会导致错误(第一条注释)您是否使用了StudentSore?如果有,请尝试此
services.addScope()
我不使用任何自定义存储。显示用户类的定义。与创建派生用户类的方法相同,您还需要创建派生用户管理器。@我现在提供了它们。您是否尝试过为每个用户类型注册标识,但使用相同的Db上下文?是的,但这似乎不可能。为什么您需要为派生类型启动单独的用户管理器?我使用UserManager来插入或获取Employee和Student用户,这在我注册一个用户类时有效。比如:User2。但我想两者都能用。@Matthijs嗯,我不知道。我建议不要使用继承,而是使用类似于
User.Role=Student
的解决方法。是的,这可能是一种解决方法。但无论如何,这应该是可能的,因为堆栈上的其他答案推荐这种方式。我为我的情况找到了另一个解决方法,但我会为其他用户输入保留此问题/悬赏。不过,谢谢你和我一起思考!谢谢你的回答。不幸的是,您的解决方案导致出现
不支持异常:存储区未实现IUserRoleStore。
@Matthijs Darn identity,注册表和登录正在工作:-(Se
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();
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<WorldContext>();