В ASP.NET Core 6 мне нужно переименовать модель базы данных ASP.NET Core Identity. Я не использую API, а просто ASP.NET Core 6 MVC.
Это мой код:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<AppUser>().ToTable("Users");
modelBuilder.Entity<AppUser>().Property(up => up.Id).HasColumnName("UserId");
modelBuilder.Entity<IdentityRole>().ToTable("Roles");
modelBuilder.Entity<IdentityUserRole<string>>().ToTable("UserRoles", "dbo");
modelBuilder.Entity<IdentityUserClaim<string>>().ToTable("UserClaims", "dbo");
modelBuilder.Entity<IdentityUserLogin<string>>().ToTable("UserLogins", "dbo");
}
Код файла программы:
builder.Services.AddDefaultIdentity<AppUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
AppUser
класс:
public partial class User : IdentityUser
Но я получаю сообщение об ошибке в этой строке кода в файле Program
:
var app = builder.Build();
Вот подробности ошибки:
System.AggregateException
HResult=0x80131500
Сообщение = Невозможно создать некоторые службы (ошибка при проверке дескриптора службы «ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory1[Microsoft.AspNetCore.Identity.IdentityUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory
1 [Microsoft.AspNetCore.Identity.IdentityUser]»: невозможно разрешить службу для типа «School.Web»). .Data.ApplicationDbContext» при попытке активировать «Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserOnlyStore6[Microsoft.AspNetCore.Identity.IdentityUser,School.Web.Data.ApplicationDbContext,System.String,Microsoft.AspNetCore.Identity.IdentityUserClaim
1[System.String],Microsoft.AspNetCore.Identity.IdentityUserLogin1[System.String],Microsoft.AspNetCore.Identity.IdentityUserToken
1[System.String]]».) (Ошибка при проверке дескриптор службы «ServiceType: Microsoft.AspNetCore.Identity.UserManager1[Microsoft.AspNetCore.Identity.IdentityUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager
1[Microsoft.AspNetCore.Identity.IdentityUser]»: невозможно разрешить службу для типа «School.Web.Data.ApplicationDbContext» при попытке активировать «Microsoft.AspNetCore.Identity» .EntityFrameworkCore.UserOnlyStore6[Microsoft.AspNetCore.Identity.IdentityUser,School.Web.Data.ApplicationDbContext,System.String,Microsoft.AspNetCore.Identity.IdentityUserClaim
1[System.String],Microsoft.AspNetCore.Identity.IdentityUserLogin1[System.String],Microsoft.AspNetCore.Identity.IdentityUserToken
1[System.String]]'.) (Ошибка при проверке дескриптора службы 'ServiceType: Microsoft.AspNetCore.Identity.ISecurityStampValidator Lifetime: Scoped) Тип реализации: Microsoft.AspNetCore.Identity.SecurityStampValidator1[Microsoft.AspNetCore.Identity.IdentityUser]': Unable to resolve service for type 'School.Web.Data.ApplicationDbContext' while attempting to activate 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserOnlyStore
6[Microsoft.AspNetCore.Identity.IdentityUser,School.Web.Data.ApplicationDbContext,System.String,Microsoft.AspNetCore.Identity.IdentityUserClaim1[System.String],Microsoft.AspNetCore.Identity.IdentityUserLogin
1[System.String],Microsoft.AspNetCore .Identity.IdentityUserToken1[System.String]]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.ITwoFactorSecurityStampValidator Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.TwoFactorSecurityStampValidator
1[Microsoft.AspNetCore.Identity.IdentityUser]': невозможно разрешить службу для типа 'School.Web.Data.ApplicationDbContext' при попытке активировать 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserOnlyStore6[Microsoft.AspNetCore.Identity.IdentityUser,School.Web.Data.ApplicationDbContext,System.String,Microsoft.AspNetCore.Identity.IdentityUserClaim
1[System .String],Microsoft.AspNetCore.Identity.IdentityUserLogin1[System.String],Microsoft.AspNetCore.Identity.IdentityUserToken
1[System.String]]'.) (Ошибка при проверке дескриптора службы 'ServiceType: Microsoft.AspNetCore.Identity.SignInManager`1[Microsoft.AspNetCore.Identity.IdentityUser]Внутреннее исключение 1: InvalidOperationException: ошибка при проверке дескриптора службы «ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory
1[Microsoft.AspNetCore.Identity.IdentityUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory
1 [Microsoft.AspNetCore.Identity.IdentityUser]»: невозможно разрешить службу для типа «School.Web.Data.ApplicationDbContext». при попытке активировать «Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserOnlyStore6[Microsoft.AspNetCore.Identity.IdentityUser,School.Web.Data.ApplicationDbContext,System.String,Microsoft.AspNetCore.Identity.IdentityUserClaim
1[System.String],Microsoft.AspNetCore.Identity.IdentityUserLogin1[System.String],Microsoft.AspNetCore.Identity.IdentityUserToken
1[System.String]]».Внутреннее исключение 2: InvalidOperationException: невозможно разрешить службу для типа «School.Web.Data.ApplicationDbContext» при попытке активировать «Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserOnlyStore
6[Microsoft.AspNetCore.Identity.IdentityUser,School.Web.Data.ApplicationDbContext,System.String,Microsoft.AspNetCore.Identity.IdentityUserClaim
1[System.String],Microsoft.AspNetCore.Identity.IdentityUserLogin1[System.String],Microsoft.AspNetCore.Identity.IdentityUserToken
1[System.String]]'.
Да, я обновил свой пост, теперь вы можете его увидеть.
Но класс AppUser находится на другом слое модели.
Убедитесь, что независимо от того, используете ли вы program.cs непосредственно для конфигураций или отдельный класс расширений, вы зарегистрировали свой dbContext и добавили идентификатор следующим образом: var ConnectionString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connectionString)); builder.Services.AddDefaultIdentity<AppUser>(options => options.SignIn.RequireConfirmedAccount = true).AddRoles<IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>();
Да, ApplicationDbContext находится в отдельном классе расширений на другом уровне.
Если у вас есть собственный AppUser
, вам также нужно будет сделать то же самое для всех связанных классов, таких как IdentityUserRole
. Кроме того, вам нужно будет использовать IdentityDbContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim>
для вашего контекста, а также применить изменения к UserManager
и SignInManager
.
@ iSR5, Да, я внес все необходимые изменения, но получаю ту же ошибку. Можете ли вы мне помочь - это нелегко сделать - я чувствую, что здесь потерялся - не могли бы вы дать мне полный код в качестве решения?
@MrMustafa022, какую сетевую версию вы используете?
Версия ASP.NET Core 6.
Привет @MrMustafa022, возникает ли исключение при запуске приложения? Я не могу воспроизвести проблему при тестировании вашего текущего кода. Возможно, вам лучше поделиться минимальным репозиторием, который может воспроизвести проблему.
Ваша главная проблема в том, что вы не прописали на таможне необходимые услуги AppUser
. Вам необходимо зарегистрировать UserManager
, RoleManager
и UserClaimsPrincipalFactory
как сервисы Scoped
с новой моделью AppUser
. Не уверен, что я что-то упустил, но чтобы иметь полный контроль над моделями удостоверений, вам придется реализовать собственную модель для каждой модели удостоверения и наследовать ее исходную модель. Кроме того, вам придется реализовать пользовательские UserManager
и RoleManager
, а также UserClaimsPrincipalFactory
.
Вот как переопределить идентификатор по умолчанию (.NET 6+) (здесь я использую int
как TKey
вместо string
, вы можете использовать string
, если хотите):
Модели идентичности
public sealed class ApplicationIdentityRole : IdentityRole<int> { }
public sealed class ApplicationIdentityRoleClaim : IdentityRoleClaim<int> { }
public sealed class ApplicationIdentityUser : IdentityUser<int> { }
public sealed class ApplicationIdentityUserClaim : IdentityUserClaim<int> { }
public sealed class ApplicationIdentityUserLogin : IdentityUserLogin<int> { }
public sealed class ApplicationIdentityUserRole : IdentityUserRole<int> { }
public sealed class ApplicationIdentityUserToken : IdentityUserToken<int> { }
Менеджеры идентификации
public sealed class ApplicationUserManager : UserManager<ApplicationIdentityUser>
{
public ApplicationUserManager(IUserStore<ApplicationIdentityUser> store, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<ApplicationIdentityUser> passwordHasher, IEnumerable<IUserValidator<ApplicationIdentityUser>> userValidators, IEnumerable<IPasswordValidator<ApplicationIdentityUser>> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<ApplicationIdentityUser>> logger) : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
}
}
public sealed class ApplicationRoleManager : RoleManager<ApplicationIdentityRole>
{
public ApplicationRoleManager(IRoleStore<ApplicationIdentityRole> store, IEnumerable<IRoleValidator<ApplicationIdentityRole>> roleValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, ILogger<RoleManager<ApplicationIdentityRole>> logger) : base(store, roleValidators, keyNormalizer, errors, logger)
{
}
}
public sealed class ApplicationUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationIdentityUser, ApplicationIdentityRole>
{
public ApplicationUserClaimsPrincipalFactory(UserManager<ApplicationIdentityUser> userManager, RoleManager<ApplicationIdentityRole> roleManager, IOptions<IdentityOptions> options) : base(userManager, roleManager, options)
{
}
}
ИдентитиДбКонтекст
public sealed class ApplicationDbContext : IdentityDbContext<ApplicationIdentityUser, ApplicationIdentityRole, int, ApplicationIdentityUserClaim, ApplicationIdentityUserRole, ApplicationIdentityUserLogin, ApplicationIdentityRoleClaim, ApplicationIdentityUserToken>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationIdentityUser>().ToTable("IdentityUsers");
modelBuilder.Entity<ApplicationIdentityRole>().ToTable("IdentityRoles");
modelBuilder.Entity<ApplicationIdentityRoleClaim>().ToTable("IdentityRoleClaims");
modelBuilder.Entity<ApplicationIdentityUserRole>().ToTable("IdentityUserRoles");
modelBuilder.Entity<ApplicationIdentityUserClaim>().ToTable("IdentityUserClaims");
modelBuilder.Entity<ApplicationIdentityUserLogin>().ToTable("IdentityUserLogins");
modelBuilder.Entity<ApplicationIdentityUserToken>().ToTable("IdentityUserTokens");
}
}
DI-услуги
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddIdentity<ApplicationIdentityUser, ApplicationIdentityRole>(options =>
{
// set Identity options here
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddUserManager<ApplicationUserManager>()
.AddRoleManager<ApplicationRoleManager>()
.AddClaimsPrincipalFactory<ApplicationUserClaimsPrincipalFactory>()
.AddDefaultTokenProviders();
Вы можете изучить остальные параметры, которые уже предоставлены в коллекции сервисов (например, AddSignInManager
), чтобы иметь представление о настраиваемых параметрах.
Привет, iSR5, но я получаю эту ошибку: связь между «RoleClaim» и «Role» со свойствами внешнего ключа {'RoleId': int} не может быть нацелена на первичный ключ {'Id': string}, поскольку он несовместим.
RoleId — это строка в RoleClaim, а идентификатор в Role также является строкой.
@MrMustafa022 измените int
на string
для всех моделей идентичности в приведенных выше примерах. Это должно решить проблему.
Да, все работает правильно, но я получаю сообщение об ошибке: SqlException: неверное имя столбца «UserId1». Недопустимое имя столбца «UserId1».
Я использую этот код, чтобы изменить идентификатор на UserId: modelBuilder.Entity<User>().Property(up => up.Id).HasColumnName("UserId");
@MrMustafa022 MrMustafa022 Я не рекомендую менять имя первичного ключа; потому что все с этим связано. Кроме того, UserId
— это имя внешнего ключа. в качестве соглашения об именовании внешнего ключа будет использоваться имя таблицы в качестве префикса и имя столбца в качестве суффикса (например, UserId). А Id
— это наиболее используемый и известный первичный ключ для любой таблицы в любой базе данных.
@MrMustafa022, если этого невозможно избежать, вам нужно будет изменить FK
для каждой связанной таблицы, такой как UserRole
, UserClaims
, UserLogins
и так далее.
Нет проблем, я меняю его на Id, и все работает правильно, но я получаю ошибку: UserManager имеет значение Null.
Код: общественный ApplicationUserManager UserManager {get {return _userManager; } Частный набор { _userManager = значение; } }
общедоступный запечатанный класс ApplicationUserManager : UserManager<User> { public ApplicationUserManager(IUserStore<User> store, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<User> парольHasher, IEnumerable<IUserValidator<User>> userValidators, IEnumerable<IPasswordValidator<User>>passwordValidators, Нормализатор keyNormalizer, ошибки IdentityErrorDescriber, службы IServiceProvider, регистратор ILogger<UserManager<User>>): base(store, optionsAccessor, парольHasher, userValidators, парольValidators, keyNormalizer, ошибки, службы, регистратор) { } }
публичный частичный класс User: IdentityUser<string>
builder.Services.AddIdentity<Пользователь, Роль>(параметры =>
Давайте продолжим обсуждение в чате.
Можете ли вы подтвердить, что правильное наследование для вас dbContext —
ApplicationDbContext : IdentityDbContext<AppUser>
и что вы правильно зарегистрировали свой dbContext вProgram.cs
?