web-dev-qa-db-ja.com

複数のIDユーザーを使用する場合、タイプIdentity.UserManagerのサービスはありません

私の設定

現在、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プロパティが含まれています。 StudentUserEmployeeUserはどちらも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 があり、プロジェクトの構造をよりよく把握できます。

16
Matthijs

理想的には、派生ユーザータイプに対して、基本ユーザータイプと同じID設定を呼び出すことになります。

残念ながら AddIdentity メソッドには、複数回使用できないようにするコードが含まれています。

代わりに、 AddIdentityCore を使用できます。役割サービスは、AddIdentityによって既に登録されています。唯一の違いは、AddIdentityCoreUserClaimsPrincipalFactory<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();

もちろん、カスタム拡張メソッドの共通部分を移動することもできます。

更新:役割サービスは既に構成されていますが、AddRolesRoleプロパティを正しく設定して使用するために、IndentityBuilderを呼び出す必要がありますAddEntityFrameworkStores

5
Ivan Stoev

そのためのレジスタ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
0
UbuntuCore

コア> = 3.0の場合

services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<WorldContext>();
0

異なるユーザータイプのスコープを追加することはできません。実際には、IdentityUserから派生した多くの異なるタイプを使用しないでください。これは、データベース全体で誤ったタイプが使用されたり、複数の異なるユーザーテーブルが使用されたりするためです。

実際にデータを構造化して、ApplicationUserが従業員エンティティ(別のエンティティ)または生徒エンティティ(別のエンティティ)によって参照されるようにする必要があります。ここでは、コードの問題ではなく、設計の問題が多くなります。

ASPIdentityはUsermanager<ApplicationUser>を実行するとAddIdentity<ApplicationUser, IdentityRole>を挿入するため、ユーザーマネージャーを追加しても期待どおりに動作しません。

答えユーザーのタイプごとに異なるエンティティを作成する必要があります。1つは学生用、1つは従業員用などです。これらはすべてユーザーのIDへの外部キーを持ち、これにより複数を追加できます。ユーザータイプごとに異なるテーブルを必要としないユーザータイプ。

次にaddIdentityを登録するとApplicationUserを(現時点では)登録でき、次にUserManager<ApplicationUser>を注入してユーザータイプを取得します。

0
Kyle B Cox