Using a Custom UserStore and RoleStore in ASP.NET 5

asp.net-core-mvc asp.net-identity-3 c# entity-framework-core

Question

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.

1
2
2/21/2017 10:02:00 AM

Popular Answer

Check out this section Reconfigure application to use new storage provider in Overview of Custom Storage Providers for ASP.NET Identity

Specifically "If the default storage provider was included in your project, you must remove the default provider and replace it with your provider."

public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
{
    var manager = new ApplicationUserManager(new YourNewUserStore(context.Get<ExampleStorageContext>()));
    ...
}
1
4/26/2016 9:56:08 PM


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