public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, Guid, UserClaim, UserRole,
UserLogin, RoleClaim, UserToken>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
public class ApplicationUser : IdentityUser<Guid, UserClaim, UserRole, UserLogin>
{
}
public class ApplicationRole : IdentityRole<Guid, UserRole, RoleClaim>
{
}
public class UserRole : IdentityUserRole<Guid>
{
}
public class RoleClaim : IdentityRoleClaim<Guid>
{
}
public class UserClaim : IdentityUserClaim<Guid>
{
}
public class UserLogin : IdentityUserLogin<Guid>
{
}
public class UserToken : IdentityUserToken<Guid>
{
}
Startup.cs
: services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext, Guid>()
.AddDefaultTokenProviders();
When the application starts, it throws the following exception:
GenericArguments[0], 'del.Models.ApplicationUser', on 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`4[TUser,TRole,TContext,TKey]' violates the constraint of type 'TUser'.
How to solve this problem? Classes "
UserRole
, RoleClaim
" is needed.
I had the same issue just today. I am heavily extending the Identity system to support things that I need in my application. One of the things I noticed is that since the IdentityUser has A LOT of different derived classes, it is not always as simple as overriding just "IdentityUser<>".
Having said that, the exception is getting thrown in the ExtensionMethod "AddEntityFrameworkStores()". The reason for this is that that extension method also uses a private helper method that dynamically creates a generic type:
userStoreType = typeof(UserStore<,,,>).MakeGenericType(userType, roleType, contextType, keyType);
UserStore<> also has a lot of different generic signatures. I created my own derived UserStore (ApplicationUserStore) so that I could create my own ApplicationUserRole. In doing that, the creation of the generic type would no longer work. I had to create my own version of the extension method that was:
userStoreType = typeof(ApplicationUserStore<,,,>).MakeGenericType(userType, roleType, contextType, keyType);
Now, this my not be your "exact" issue, but I'm 99% sure this is it. You may need to create your own derived UserStore using the following signature:
public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, ApplicationDbContext, Guid>
{
...
}
Then create a new Extensions method class that duplicates the original but changes the UserStore creation.
public static class IdentityEntityFrameworkBuilderExtensions2
{
public static IdentityBuilder AddEntityFrameworkStores2<TContext>(this IdentityBuilder builder)
where TContext : DbContext
{
builder.Services.TryAdd(GetDefaultServices(builder.UserType, builder.RoleType, typeof(TContext)));
return builder;
}
public static IdentityBuilder AddEntityFrameworkStores2<TContext, TKey>(this IdentityBuilder builder)
where TContext : DbContext
where TKey : IEquatable<TKey>
{
builder.Services.TryAdd(GetDefaultServices(builder.UserType, builder.RoleType, typeof(TContext), typeof(TKey)));
return builder;
}
private static IServiceCollection GetDefaultServices(Type userType, Type roleType, Type contextType, Type keyType = null)
{
Type userStoreType;
Type roleStoreType;
keyType = keyType ?? typeof(string);
userStoreType = typeof(ApplicationUserStore<,,,>).MakeGenericType(userType, roleType, contextType, keyType);
roleStoreType = typeof(ApplicationRoleStore<,,>).MakeGenericType(roleType, contextType, keyType);
var services = new ServiceCollection();
services.AddScoped(
typeof(IUserStore<>).MakeGenericType(userType),
userStoreType);
services.AddScoped(
typeof(IRoleStore<>).MakeGenericType(roleType),
roleStoreType);
return services;
}
}
Hopefully this helps.