In ASP.NET Core 6, I need to rename the database model of ASP.NET Core Identity. I do not use APIs, but just ASP.NET Core 6 MVC.
This my code:
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");
}
Program file code:
builder.Services.AddDefaultIdentity<AppUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
AppUser
class:
public partial class User : IdentityUser
But I get an error at this line of code in Program
file:
var app = builder.Build();
These are the error details:
System.AggregateException
HResult=0x80131500
Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory1[Microsoft.AspNetCore.Identity.IdentityUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory
1[Microsoft.AspNetCore.Identity.IdentityUser]': Unable to resolve service for type 'School.Web.Data.ApplicationDbContext' while attempting to activate '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]]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.UserManager1[Microsoft.AspNetCore.Identity.IdentityUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager
1[Microsoft.AspNetCore.Identity.IdentityUser]': Unable to resolve service for type 'School.Web.Data.ApplicationDbContext' while attempting to activate '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]]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.ISecurityStampValidator Lifetime: Scoped ImplementationType: 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]': Unable to resolve service for type 'School.Web.Data.ApplicationDbContext' while attempting to activate '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]]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.SignInManager`1[Microsoft.AspNetCore.Identity.IdentityUser]Inner exception 1: InvalidOperationException: error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory
1[Microsoft.AspNetCore.Identity.IdentityUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory
1[Microsoft.AspNetCore.Identity.IdentityUser]': Unable to resolve service for type 'School.Web.Data.ApplicationDbContext' while attempting to activate '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]]'.Inner exception 2: InvalidOperationException: 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.IdentityUserClaim
1[System.String],Microsoft.AspNetCore.Identity.IdentityUserLogin1[System.String],Microsoft.AspNetCore.Identity.IdentityUserToken
1[System.String]]'.
Your main issue is that you didn't register the required services with the custom AppUser
. You need to register UserManager
, RoleManager
and UserClaimsPrincipalFactory
as Scoped
services with the new AppUser
model. Not sure if I missed something here, but to have a full control on identity models, you will have to implement custom model for each identity model and inherit from its original model. Also, you will have to implement custom UserManager
and RoleManager
and also UserClaimsPrincipalFactory
.
Here is how to override the default Identity (.NET 6+) (here I use int
as TKey
instead of string
you can use string
if you like) :
Identity Models
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> { }
Identity Managers
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)
{
}
}
IdentityDbContext
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 Services
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();
You can explore the rest of the options that already provided via the service collection (e.g. AddSignInManager
), to have an idea on the configurable options.