私の設定
現在、ApplicationUser
を継承する2つのモデルがあり、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
には、姓名などのsharedプロパティが含まれています。 StudentUser
とEmployeeUser
はどちらもownプロパティと関係を持っています。この構造は 階層ごとのテーブル(TPH) 継承に従います。
理想的には、SQL構造の方が優れているため、 Table Per Type(TPT) 継承に従いたいと思います。 ASP.NET CoreはネイティブでTPHのみをサポートしているため、TPTアプローチを採用しています。
問題
IdentityサービスをStartup.cs
に追加しました:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
UserManager<StudentUser>
またはUserManager<EmployeeUser>
を呼び出すと、次のエラーが発生します。
タイプ「Microsoft.AspNetCore.Identity.UserManager`1 [ClassroomMonitor.Models.StudentUser]」のサービスは登録されていません。
私の質問
残念ながら、この実装と組み合わせたこのエラーについてはあまりわかりません。
このように機能させることは可能ですか?
どんな助けや考えでも大歓迎です。
更新1
スコープサービスとしてStudentUser
またはEmployeeUser
を手動で追加することは機能しないようです(最初の answer と記載されています)。
services.AddScoped<UserManager<ApplicationUser>, UserManager<ApplicationUser>>();
// or..
services.AddScoped<UserManager<ApplicationUser>>();
これにより、次のエラーがスローされます。
InvalidOperationException:タイプ 'Microsoft.AspNetCore.Identity.IUserStore1 [ClassroomMonitor.Models.StudentUser]'のサービスを解決できません
更新2
ここに Gist があり、プロジェクトの構造をよりよく把握できます。
理想的には、派生ユーザータイプに対して、基本ユーザータイプと同じID設定を呼び出すことになります。
残念ながら 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
。
そのためのレジスタDIがありません。
services.AddScoped<UserManager<AppUser>, UserManager<AppUser>>()
StudentUserとEmployeeUserはそれに似ています
新しいプロジェクトでテスト済み:
dotnet new mvc --auth個別
Startup.cshtml
services.AddDefaultIdentity<User>()
.AddEntityFrameworkStores<ApplicationDbContext>();
User.cs
public class User : IdentityUser
{
public string Test { get; set; }
}
おそらくここにあなたの問題があります:
_LoginPartial.cshtml
@inject SignInManager<User> SignInManager
@inject UserManager<User> UserManager
この方法でもテストされました:
Startup.cs
services.AddDefaultIdentity<User2>()
.AddEntityFrameworkStores<ApplicationDbContext>();
Users.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
コア> = 3.0の場合
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<WorldContext>();
異なるユーザータイプのスコープを追加することはできません。実際には、IdentityUserから派生した多くの異なるタイプを使用しないでください。これは、データベース全体で誤ったタイプが使用されたり、複数の異なるユーザーテーブルが使用されたりするためです。
実際にデータを構造化して、ApplicationUser
が従業員エンティティ(別のエンティティ)または生徒エンティティ(別のエンティティ)によって参照されるようにする必要があります。ここでは、コードの問題ではなく、設計の問題が多くなります。
ASPIdentityはUsermanager<ApplicationUser>
を実行するとAddIdentity<ApplicationUser, IdentityRole>
を挿入するため、ユーザーマネージャーを追加しても期待どおりに動作しません。
答えユーザーのタイプごとに異なるエンティティを作成する必要があります。1つは学生用、1つは従業員用などです。これらはすべてユーザーのIDへの外部キーを持ち、これにより複数を追加できます。ユーザータイプごとに異なるテーブルを必要としないユーザータイプ。
次にaddIdentity
を登録するとApplicationUser
を(現時点では)登録でき、次にUserManager<ApplicationUser>
を注入してユーザータイプを取得します。