簡體   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