Search code examples
asp.net-mvcasp.net-mvc-5asp.net-identity-2asp.net-rolesdiscriminator

Add custom column in AspNetRoles results in Invalid Column Name Discriminator


I'm using ASP.NET MVC5 with Identity 2 framework, Database first

I'm trying to custom AspNetRoles, by adding a column called MyCustomColumn

However, my app crashes because :

Invalid Column Name Discriminator

There is a lot of resources on SO and elsewhere on the web, but most of them are with CodeFirst approach and I can't use them in my app.

How to deal with it ?


Solution

  • Ok, as I spend some hours to find a solution, I post it here, if it could help someone else.

    First, in AspNetRoles, create your custom column AND a column called Discriminator (which is a nvarchar(max) ). Update your .edmx

    Then, we have to create a class which inherits from IdentityRole. We will use this class to access our custom column we just created :

    In Models folder

    public ApplicationRole()
            : base() { }
    
        public ApplicationRole(string name, long myCustomValue)
            : base(name)
        {
            MyCustomValue = myCustomValue;
        }
    
        public virtual long MyCustomValue { get; set; }
    


    Then, let's create a class which inherits from RoleManager<ApplicationRole>. I placed it in IdentityConfig.cs, but maybe it's a best practice to place it elsewhere...
    For information, I get inspired by this blog, Re-Implementing RoleStore and ApplicationRoleManager paragraph

    public class ApplicationRoleManager : RoleManager<ApplicationRole>
    {
        public ApplicationRoleManager(
            IRoleStore<ApplicationRole, string> roleStore)
            : base(roleStore)
        {
        }
        public static ApplicationRoleManager Create(
            IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
        {
            return new ApplicationRoleManager(
                new RoleStore<ApplicationRole>(context.Get<ApplicationDbContext>()));
        }
    }
    

    ApplicationRoleManager has a constructor which calls our previously created ApplicationRole class.

    Now we have to register our ApplicationRoleManager at startup, so we have to add this line after the others CreatePerOwinContext

    In App_Start\Startup.auth.cs, ConfigureAuth(IAppBuilder app) method

    app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
    


    So now we can use our ApplicationRoleManager, correctly instanciated :

    var rm = new ApplicationRoleManager(new RoleStore<ApplicationRole>(new ApplicationDbContext()));
    

    And then use it as we want

    var roleName = rm.FindByName("Admin");
    string myCustomData = roleName.CustomData.ToString();