I have implemented a custom RoleStore and a custom UserStore for my project that is using ASP.NET 5, MVC 6, EF 7, and Identity 3. However - I can't quite figure out how to configure identity to use my custom RoleStore and custom UserStore instead of the usual offering. How can I reconfigure the system to use my custom classes?
PS: I also have custom User and Role class.
Solution
Here's what I ended up doing. First, I uninstalled the 'Identity Entity Framework' package from my project. This sent a few things missing, so I re-implemented them (read: copied them from here), and put them in a 'Standard' namespace to indicate they hadn't been customised. I now have a 'Security' namespace that contains the following:
- Standard
- IdentityRole.cs
- IdentityRoleClaim.cs
- IdentityUser.cs
- IdentityUserClaim.cs
- IdentityUserLogin.cs
- IdentityUserRole.cs
- BuilderExtensions.cs
- IdentityDbContext.cs
- Resources.resx
- Role.cs
- RoleStore.cs
- User.cs
- UserStore.cs
The items shown in bold contain project specific functionality.
The code that allows me to use the custom stores is in the 'BuilderExtensions' file, which contains the following class:
public static class BuilderExtensions
{
public static IdentityBuilder AddCustomStores<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)
{
var userStoreType = typeof(UserStore<,,,>).MakeGenericType(userType, roleType, contextType, keyType);
var roleStoreType = typeof(RoleStore<,,>).MakeGenericType(roleType, contextType, keyType);
var services = new ServiceCollection();
services.AddScoped(
typeof(IUserStore<>).MakeGenericType(userType),
userStoreType);
services.AddScoped(
typeof(IRoleStore<>).MakeGenericType(roleType),
roleStoreType);
return services;
}
}
This then allows me to write the following in my Startup.cs file:
services.AddIdentity<User, Role>()
.AddCustomStores<PrimaryContext, string>()
.AddDefaultTokenProviders();
And the custom store will be used. Note that PrimaryContext is the name of my whole-project DbContext. it inherits from IdentityDbContext.
Discussion
I could have probably kept the 'Identity Entity Framework' package and saved myself duplicating the contents of the 'Standard' namespace, but I chose not to so that I can keep my identifiers short and unambiguous.