I am trying to create database from Code first model. When I run dotnet ef migrations add
or debug application I get error:
TypeLoadException: GenericArguments[0], 'OpPISWeb.Models.AppUser', on 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`9[TUser,TRole,TContext,TKey,TUserClaim,TUserRole,TUserLogin,TUserToken,TRoleClaim]' violates the constraint of type parameter 'TUser'.
System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle handle, IntPtr* pInst, int numGenericArgs, ObjectHandleOnStack type)
in code:
.AddEntityFrameworkStores<AppWebContext, int>()
My code in ConfigureServices is:
var res = services
.AddIdentity<AppUser, AppRole>(config =>
{
config.User.RequireUniqueEmail = true;
config.Password.RequireNonAlphanumeric = false;
config.Cookies.ApplicationCookie.AutomaticChallenge = false;
})
.AddEntityFrameworkStores<AppWebContext, int>()
.AddDefaultTokenProviders();
and my EF models are:
[Table("Roles")]
public partial class AppRole : IdentityRole<int, AppUserRole, AppRoleClaim>
{
}
[Table("RoleClaims")]
public partial class AppRoleClaim : IdentityRoleClaim<int>
{
}
[Table("Users")]
public partial class AppUser : IdentityUser<int, AppUserClaim, AppUserRole, AppUserLogin>
{
}
//same for UserClaim, UserLogin, UserRole, UserToken
and my DBContext:
public partial class AppWebContext : IdentityDbContext<AppUser, AppRole, int, AppUserClaim, AppUserRole, AppUserLogin, AppRoleClaim, AppUserToken>
{
public AppWebContext() : base() {
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=...");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<AppUser>(entity =>
{
entity
.HasKey(u => u.Id);
entity.Property(p => p.Id)
.ValueGeneratedOnAdd();
});
modelBuilder.Entity<AppRole>(entity =>
{
entity
.HasKey(u => u.Id);
entity.Property(p => p.Id)
.ValueGeneratedOnAdd();
});
modelBuilder.Entity<AppUserClaim>(entity =>
{
entity
.HasKey(u => u.Id);
entity.Property(p => p.Id)
.ValueGeneratedOnAdd();
});
modelBuilder.Entity<AppUserRole>(entity =>
{
entity
.HasKey(u => new { u.RoleId, u.UserId });
});
modelBuilder.Entity<AppRoleClaim>(entity =>
{
entity
.HasKey(u => u.Id);
entity.Property(p => p.Id)
.ValueGeneratedOnAdd();
});
}
}
What did I miss? I am new in ASP.net and ASP.NET Core.
I am using version 1.1.
Complete error:
An error occurred while starting the application.
TypeLoadException: GenericArguments[0], 'OpPISWeb.Models.AppUser', on 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`9[TUser,TRole,TContext,TKey,TUserClaim,TUserRole,TUserLogin,TUserToken,TRoleClaim]' violates the constraint of type parameter 'TUser'.
System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle handle, IntPtr* pInst, int numGenericArgs, ObjectHandleOnStack type)
ArgumentException: GenericArguments[0], 'OpPISWeb.Models.AppUser', on 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`4[TUser,TRole,TContext,TKey]' violates the constraint of type 'TUser'.
System.RuntimeType.ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
TypeLoadException: GenericArguments[0], 'OpPISWeb.Models.AppUser', on 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`9[TUser,TRole,TContext,TKey,TUserClaim,TUserRole,TUserLogin,TUserToken,TRoleClaim]' violates the constraint of type parameter 'TUser'.
System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle handle, IntPtr* pInst, int numGenericArgs, ObjectHandleOnStack type)
System.RuntimeTypeHandle.Instantiate(Type[] inst)
System.RuntimeType.MakeGenericType(Type[] instantiation)
Show raw exception details
ArgumentException: GenericArguments[0], 'OpPISWeb.Models.AppUser', on 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`4[TUser,TRole,TContext,TKey]' violates the constraint of type 'TUser'.
System.RuntimeType.ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
System.RuntimeType.MakeGenericType(Type[] instantiation)
Microsoft.Extensions.DependencyInjection.IdentityEntityFrameworkBuilderExtensions.GetDefaultServices(Type userType, Type roleType, Type contextType, Type keyType)
Microsoft.Extensions.DependencyInjection.IdentityEntityFrameworkBuilderExtensions.AddEntityFrameworkStores<TContext, TKey>(IdentityBuilder builder)
OpPISWeb.Startup.ConfigureServices(IServiceCollection services)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Hosting.ConventionBasedStartup.ConfigureServices(IServiceCollection services)
Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureApplicationServices()
Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
Show raw exception details
.NET Core X64 v4.1.1.0 | Microsoft.AspNetCore.Hosting version 1.1.0-rtm-22752 | Microsoft Windows 10.0.14393 | Need help? - Yes I do. Please.
Your problem is caused by .AddEntityFrameworkStores<AppWebContext, int>()
. Take a look at HaoK's responses toward the end of this post:
https://github.com/aspnet/Identity/issues/1001.
Specially these 2
"AddEntityFrameworkStores can only be called with a user that derives from IdentityUser. If you are specifying more generic arguments, use IdentityBuilder.AddUserStore() instead."
"AddEntityFrameworkStores can only be called with a role that derives from IdentityRole. If you are specifying more generic arguments, use IdentityBuilder.AddRoleStore() instead."
So if you want to override UserClaim
, UserLogin
and all others, you need to implement your own UserStore
and RoleStore
, and use AddUserStore<T>()
and AddRoleStore<T>()
instead of AddEntityFrameworkStores
.
AppUserStore
public class AppUserStore : UserStore<AppUser, AppRole, AppDbContext, int, AppUserClaim, AppUserRole, AppUserLogin, AppUserToken, AppRoleClaim>
{
public AppUserStore(AppDbContext dbContext)
: base(dbContext)
{
}
protected override AppUserToken CreateUserToken(AppUser user, string loginProvider, string name, string value)
{
throw new NotImplementedException();
}
protected override AppUserLogin CreateUserLogin(AppUser user, UserLoginInfo login)
{
throw new NotImplementedException();
}
protected override AppUserRole CreateUserRole(AppUser user, AppRole role)
{
throw new NotImplementedException();
}
protected override AppUserClaim CreateUserClaim(AppUser user, Claim claim)
{
throw new NotImplementedException();
}
}
AppRoleStore
public class AppRoleStore : RoleStore<AppRole, AppDbContext, int, AppUserRole, AppRoleClaim>
{
public AppRoleStore(AppDbContext dbContext)
: base(dbContext)
{
}
protected override AppRoleClaim CreateRoleClaim(AppRole role, Claim claim)
{
throw new NotImplementedException();
}
}
And in your Startup.cs
:
services.AddIdentity<AppUser, AppRole>()
.AddUserStore<AppUserStore>()
.AddRoleStore<AppRoleStore>()
// Components that generate the confirm email and reset password tokens
.AddDefaultTokenProviders();
Now I do think you need to create your own version of UserManager
, RoleManager
and SignInManager
as well. I will update with more codes here later on after I figure everything out.