Нет службы для типа Identity.UserManager при использовании нескольких пользователей удостоверений - PullRequest
0 голосов
/ 08 октября 2018

Моя настройка

В настоящее время у меня есть две модели, которые наследуются от 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:

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

Вот Gist , чтобы дать вам более полное представление о структуре проекта:

Ответы [ 4 ]

0 голосов
/ 17 октября 2018

Вы не можете добавить область для разных типов пользователей, у вас действительно не должно быть много разных типов, производных от IdentityUser, так как это будет означать, что у вас будут неправильные типы, используемые повсеместно, или несколько разных пользовательских таблиц в базе данных.

вы действительно должны структурировать свои данные таким образом, чтобы они имели ApplicationUser, на который ссылается сущность сотрудника (отдельная сущность) или сущность Student (опять же отдельная сущность).здесь проблема скорее в дизайне, чем в коде.

ASPIdentity будет вставлять Usermanager<ApplicationUser> при AddIdentity<ApplicationUser, IdentityRole>, поэтому добавление большего количества менеджеров пользователей не будет работать должным образом.

Ответ Вы должны создать разные сущности для каждого типа пользователя, 1 для студента, 1 для сотрудника и т. Д. Все они будут иметь внешний ключ для идентификатора пользователя, что позволит вам добавлять несколько типовпользователя без необходимости использовать разные таблицы для каждого типа пользователя.

, затем, когда вы addIdentity, вы можете зарегистрировать ApplicationUser (как на данный момент), а затем ввести UserManager<ApplicationUser>, который получит тип пользователя.

0 голосов
/ 10 октября 2018

Проверено на новом проекте:

dotnet new mvc --auth Individual

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 голосов
/ 17 октября 2018

В идеале вы должны вызывать ту же настройку идентичности для производных типов пользователей, что и для базового типа пользователя.

К сожалению, AddIdentity метод содержит некоторый код, который не позволяет использовать его болееодин раз.

Вместо этого вы можете использовать AddIdentityCore.Службы ролей уже зарегистрированы в AddIdentity, единственное отличие состоит в том, что AddIdentityCore регистрирует UserClaimsPrincipalFactory<TUser>, поэтому для соответствия настройке AddIdentity его необходимо заменить на UserClaimsPrincipalFactory<TUser, TRole> через AddClaimsPrincipalFactory method.

Код выглядит примерно так:

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.

0 голосов
/ 08 октября 2018

Вам не хватает регистра DI для этого.

services.AddScoped<UserManager<AppUser>, UserManager<AppUser>>()

StudentUser и EmployeeUser похожи на это

...