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>();