Why this violates the constraint of type parameter 'TUser'?
I faced this issue, i found this: "When you are customizing ASP.NET Core Identity, you should not use AddEntityFrameworkStores anymore." you should implement yours:
public class ApplicationRoleManager: RoleManager<Role>
public class ApplicationRoleStore : RoleStore<Role, ApplicationDbContext, int, UserRole, RoleClaim>
public class ApplicationSignInManager : SignInManager<User>
public class ApplicationUserManager : UserManager<User>
public class ApplicationUserStore : UserStore<User, Role, ApplicationDbContext, int, UserClaim, UserRole, UserLogin, UserToken, RoleClaim>
And Then redirect built-in services to your custom services (Startup.cs):
services.AddScoped<UserStore<User, Role, ApplicationDbContext, int, UserClaim, UserRole, UserLogin, UserToken, RoleClaim>, ApplicationUserStore> ();
services.AddScoped<UserManager<User>, ApplicationUserManager>();
services.AddScoped<RoleManager<Role>, ApplicationRoleManager>();
services.AddScoped<SignInManager<User>, ApplicationSignInManager>();
services.AddScoped<RoleStore<Role, ApplicationDbContext, int, UserRole, RoleClaim>, ApplicationRoleStore>();
services.AddScoped<IEmailSender, AuthMessageSender>();
services.AddScoped<ISmsSender, AuthMessageSender>();
Then introduce your custom services:
services.AddIdentity<User, Role>(identityOptions =>
{
// ...
}).AddUserStore<ApplicationUserStore>()
.AddUserManager<ApplicationUserManager>()
.AddRoleStore<ApplicationRoleStore>()
.AddRoleManager<ApplicationRoleManager>()
.AddSignInManager<ApplicationSignInManager>()
// You **cannot** use .AddEntityFrameworkStores() when you customize everything
//.AddEntityFrameworkStores<ApplicationDbContext, int>()
.AddDefaultTokenProviders();
The problem is here RoleClaim
must be of type IdentityRoleClaim<TKey>
where TRole : IdentityRole<TKey, TUserRole, IdentityRoleClaim<TKey>>
instead of TRoleClaim
where TRole : IdentityRole<TKey, TUserRole, TRoleClaim>
It's reported here as a bug.
- According to MSDN, the constraint for
UserStore<TUser>
isTUser : IdentityUser
. - Also according to MSDN,
IdentityUser : IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
. - According to your declarations,
User : IdentityUser<string, UserClaim, UserRole, UserLogin>
.
The long names make it easy to miss, so let's alias IdentityUser
as D
and IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
as B
. Now the above can be restated as:
TUser : D
(aTUser
must be a kind ofD
)D : B
(D
is a kind ofB
)User : B
(yourUser
is a kind ofB
in general but not a kind ofD
specifically, as required)