[英]'No service for type 'Identity.UserManager`1[ProjectName.ApplicationUser]' has been registered.able when container is destroy)'
[英]No service for type Identity.UserManager when using multiple identity users
我的设置
目前,我有两个继承自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
都有自己的属性和关系。 此结构遵循Table Per Hierarchy (TPH)继承。
理想情况下,我想遵循Table Per Type (TPT)继承,因为 SQL 结构更好。 ASP.NET Core 本身只支持 TPH,所以这就是我遵循 TPT 方法的原因。
问题
我在Startup.cs
添加了 Identity 服务:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
当我调用UserManager<StudentUser>
或UserManager<EmployeeUser>
,出现以下错误:
没有注册“Microsoft.AspNetCore.Identity.UserManager`1[ClassroomMonitor.Models.StudentUser]”类型的服务。
我的问题
不幸的是,我无法找到有关此错误与此实现相结合的太多信息。
是否(甚至)有可能让它以这种方式工作?
欢迎任何帮助或想法。
更新 1
手动添加StudentUser
或EmployeeUser
作为范围服务似乎不起作用(作为第一个答案提到)。
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
设置,它需要通过AddClaimsPrincipalFactory
方法替换为UserClaimsPrincipalFactory<TUser, TRole>
。
代码看起来像这样:
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
。
在新项目上测试:
dotnet new mvc --auth 个人
启动.cshtml
services.AddDefaultIdentity<User>()
.AddEntityFrameworkStores<ApplicationDbContext>();
用户.cs
public class User : IdentityUser
{
public string Test { get; set; }
}
可能这是你的问题:
_LoginPartial.cshtml
@inject SignInManager<User> SignInManager
@inject UserManager<User> UserManager
也这样测试:
启动文件
services.AddDefaultIdentity<User2>()
.AddEntityFrameworkStores<ApplicationDbContext>();
用户.cs
public class User : IdentityUser
{
public string TestA { get; set; }
}
public class User2 : User
{
public string TestB { get; set; }
}
_LoginPartial.cshtml
@inject SignInManager<User2> SignInManager
@inject UserManager<User2> UserManager
您缺少它的注册 DI。
services.AddScoped<UserManager<AppUser>, UserManager<AppUser>>()
StudentUser 和 EmployeeUser 类似
你不能为不同的用户类型添加范围,你真的不应该有很多从 IdentityUser 派生的不同类型,因为这意味着你要么在整个地方使用不正确的类型,要么在数据库中使用多个不同的用户表。
您应该真正构建您的数据,以便它有一个ApplicationUser
,它被员工实体(一个单独的实体)或 Student 实体(又一个单独的实体)引用。 这里有更多的设计问题而不是代码问题。
当您AddIdentity<ApplicationUser, IdentityRole>
,ASPIdentity 将注入Usermanager<ApplicationUser>
,因此添加更多用户管理器将无法按预期工作。
答案是您必须为每种类型的用户创建不同的实体,1 个用于学生,1 个用于员工等。这些都将具有用户 ID 的外键,这将使您能够添加多种类型的用户,而无需每个用户类型不同的表。
然后,当您addIdentity
您可以注册ApplicationUser
(目前如此),然后注入UserManager<ApplicationUser>
这将获取用户类型。
如果核心>=3.0
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<WorldContext>();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.