问题
I'm building a completely custom AspNetCore.Identity Implementation because I want TKey to be System.Guid across the board. With respect, I have derived types for...
Role : IdentityRole<Guid, UserRole, RoleClaim>RoleClaim : IdentityRoleClaim<Guid>User : IdentityUser<Guid, UserClaim, UserRole, UserLogin>UserClaim : IdentityUserClaim<Guid>UserLogin : IdentityUserLogin<Guid>UserRole : IdentityUserRole<Guid>UserToken : IdentityUserToken<Guid>ApplicationDbContext : IdentityDbContext<User, Role, Guid, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>ApplicationRoleManager : RoleManager<Role>ApplicationRoleStore : RoleStore<Role, ApplicationDbContext, Guid, UserRole, RoleClaim>ApplicationSignInManager : SignInManager<User>ApplicationUserManager : UserManager<User>**ApplicationUserStore** : UserStore<User, Role, ApplicationDbContext, Guid, UserClaim, UserRole, UserLogin, UserToken>
ApplicationUserStore is the problem child!
Implementation
namespace NewCo.Identity
{
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using System;
public sealed class Role : IdentityRole<Guid, UserRole, RoleClaim>
{
}
}
namespace NewCo.Identity
{
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using System;
public sealed class UserRole : IdentityUserRole<Guid>
{
}
}
namespace NewCo.Identity
{
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using System;
public sealed class RoleClaim : IdentityRoleClaim<Guid>
{
}
}
// The problem is here...
namespace NewCo.Identity
{
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using System;
using System.Security.Claims;
public sealed class ApplicationUserStore : UserStore<User, Role, ApplicationDbContext, Guid, UserClaim, UserRole, UserLogin, UserToken>
{
}
}
Error
The type 'NewCo.Identity.Role' cannot be used as type parameter 'TRole' in the generic type or method 'UserStore'. There is no implicit reference conversion from 'NewCo.Identity.Role' to 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole>'.
As far as I can see, unless this is some (co/contra/in)variance issue, all the code checks out...what did I get wrong?
回答1:
Your ApplicationUserStore needs the RoleClaim at the end too (don't forget to update the related NuGet packages, otherwise you can't use these new additions):
ApplicationUserStore : UserStore<
User, Role, ApplicationDbContext,
Guid, UserClaim, UserRole,
UserLogin, UserToken, RoleClaim>
Plus your ApplicationRoleStore should provide how to create the RoleClaim,
protected override RoleClaim CreateRoleClaim(Role role, Claim claim)
{
return new RoleClaim
{
RoleId = role.Id,
ClaimType = claim.Type,
ClaimValue = claim.Value
};
}
And also the ApplicationUserStore should provide these mappings too:
protected override UserClaim CreateUserClaim(User user, Claim claim)
{
var userClaim = new UserClaim { UserId = user.Id };
userClaim.InitializeFromClaim(claim);
return userClaim;
}
protected override UserLogin CreateUserLogin(User user, UserLoginInfo login)
{
return new UserLogin
{
UserId = user.Id,
ProviderKey = login.ProviderKey,
LoginProvider = login.LoginProvider,
ProviderDisplayName = login.ProviderDisplayName
};
}
protected override UserRole CreateUserRole(User user, Role role)
{
return new UserRole
{
UserId = user.Id,
RoleId = role.Id
};
}
protected override UserToken CreateUserToken(User user, string loginProvider, string name, string value)
{
return new UserToken
{
UserId = user.Id,
LoginProvider = loginProvider,
Name = name,
Value = value
};
}
Then redirect built-in services to your custom services:
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>();
now 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();
来源:https://stackoverflow.com/questions/45127666/asp-net-core-custom-aspnetcore-identity-implementation-not-working