繁体   English   中英

使用多个身份用户时,没有 Identity.UserManager 类型的服务

[英]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包含共享属性,例如名字和姓氏。 StudentUserEmployeeUser都有自己属性和关系。 此结构遵循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

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

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM