asp.net core authentication with IdentityDbContext

asp.net-core asp.net-mvc entity-framework entity-framework-6

Question

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.
1
1
1/17/2017 5:50:50 PM

Accepted Answer

When you are customizing ASP.NET Core Identity, you should not use AddEntityFrameworkStores anymore. Because it will override all of your previous settings and customization to default Identity services.

Quote from Github answer here.

0
1/24/2017 9:48:35 AM

Popular Answer

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.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow