c# - 使用多个身份用户时,Identity.UserManager 类型没有服务
问题描述
我的设置
目前,我有两个继承自的模型,继承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
。此结构遵循按层次结构表 (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
手动添加StudentUser
orEmployeeUser
作为范围服务似乎不起作用(作为第一个答案提到)。
services.AddScoped<UserManager<ApplicationUser>, UserManager<ApplicationUser>>();
// or..
services.AddScoped<UserManager<ApplicationUser>>();
这会引发以下错误:
InvalidOperationException:无法解析“Microsoft.AspNetCore.Identity.IUserStore1[ClassroomMonitor.Models.StudentUser]”类型的服务
更新 2
这是一个要点,可以让您更好地了解项目结构:
解决方案
理想情况下,您会为派生用户类型调用与基本用户类型相同的身份设置。
不幸的是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
.
推荐阅读
- powershell - 如何同时激活 Anaconda 环境和 Typescript 观察者?
- java - 如何在 CMD 中分离 Java 程序的输出?
- python - 如何在广度优先树中存储节点到根的距离?
- mongodb - 来自 mongod 4.4 命令的不可读终端日志
- laravel - Laravel Livewire 2.x 正在向 URL 添加查询字符串如何禁用它
- c - 全局变量的分叉和信号问题
- php - 用while循环左连接PHP
- javascript - Redux Reducer => 无法将 undefined 或 null 转换为对象
- javascript - 如何使用 vue 和 vuetify 在选择中显示对象中的元素列表
- r - data.table::melt 中的变量值与模式