0

IdentityDbContext causing problems for properties/fields added to AspNetRoles

I believe the problem is here with IdentityDbContext taking an IdentityUser type:

public class MyIdentityDb : IdentityDbContext<ApplicationUser>
{
    public IdentityDb()
        : base("IdentityDb")
    {
    }
}

But let me explain…

It is wonderful that we can add fields to the AspNetUsers table by adding properties to our ApplicationUser class that inherits from IdentityUser. Example:

public class ApplicationUser : IdentityUser
    {
        [Required]
        [StringLength(50)]
        public string FirstName { get; set; }

        [Required]
        [StringLength(50)]
        public string LastName { get; set; }
    }

So natural we can add fields to the AspNetRoles table by adding properties to an ApplicationRole class that inherits from IdentityRole. Example:

public class ApplicationRole : IdentityRole
{
    [Required]
    [StringLength(50)]
    public string ProperName { get; set; }
}

Works perfect. We can see the field in the database. We can add data to it. Example:

RoleManager<ApplicationRole> roleManager = new RoleManager<ApplicationRole>(new RoleStore<ApplicationRole>(new MyIdentityDb()));

var role = new ApplicationRole() { Name = name, ProperName = propername };
var result = await roleManager.CreateAsync(role);

But now we run into a problem when trying to get to the data. Example:

Our ViewModel:

public class IndexViewModel
{
    public IList<ApplicationUser> Users { get; set; }
    public IList<ApplicationRole> Roles { get; set; }
}

On our Controller:

private MyIdentityDb myIdentityDb = new MyIdentityDb();

Our Index method on our controller:

public ViewResult Index(int? page)
{
     return View(new IndexViewModel
     {
          Users = myIdentityDb.Users.ToList(),
          Roles = myIdentityDb.Roles.ToList()
     });
}

The error is on “myIdentityDb.Roles.ToList()” and reads “Cannot implicitly convert type System.Collection.Generic.List<Microsoft.AspNet.Identity.EntityFramework.IdentityRole> to System.Collections.Generic.IList<MyApp.Models.ApplicationRole>

Of course we could change our ViewModel to use type IdentityRole like the following example, but then we cannot get to the new “ProperName” field in the AspNetRoles table:

public class IndexViewModel
{
    public IList<ApplicationUser> Users { get; set; }
    public IList<IdentityRole> Roles { get; set; }
}

So we could try creating another Db class and pass it an IdentityRole type instead of IdentityUser:

public class MyIdentityDb : IdentityDbContext<ApplicationUser>
{
    public MyIdentityDb()
        : base("MyIdentityDb")
    {
    }
}

public class MyIdentityRolesDb : IdentityDbContext<ApplicationRole>
{
    public MyIdentityRolesDb()
        : base("MyIdentityDb")
    {
    }
}

And change our controller:

private MyIdentityDb myIdentityDb = new MyIdentityDb();
private MyIdentityRolesDb myIdentityRolesDb = new MyIdentityRolesDb();

And change our Index method on our controller:

public ViewResult Index(int? page)
{
     return View(new IndexViewModel
     {
          Users = myIdentityDb.Users.ToList(),
          Roles = myIdentityRolesDb.Roles.ToList()
     });
}

But we end up with the same problem; the fact that IdentityDbContext takes an IdentityUser type.

Any ideas how we can get a list of Roles with the custom fields/properties?

Sean Newcome
  • 1,497
  • 2
  • 17
  • 24

2 Answers2

1

Please take a look at the following article which explains in detail what you are trying to do http://typecastexception.com/post/2014/02/13/ASPNET-MVC-5-Identity-Extending-and-Modifying-Roles.aspx

pranav rastogi
  • 4,124
  • 23
  • 23
  • Hopefully the Asp.Net-Identity folks will make the IdentityDbContext work like DbContext and just expose all the tables and all the fields. It is great we can add fields so easily to the tables--how much better it would be if they were easy to use! – Sean Newcome Feb 26 '14 at 20:41
  • @Pranav would you mind adding a little summary? Link-only answers are of limited value because sooner or later the link will break. – Gert Arnold Feb 26 '14 at 20:47
  • @Pranav while the article, in the end, does expose the fields added to the AspNetRoles table, it uses a new class 'IdentityManager' that has a 'RoleManager'. It doesn't explain why or how (from my code above) we can get to the new fields created on AspNetUsers with the {myIdentityDb.Users.ToList();} but not get to the new fields created on AspNetRoles with {myIdentityDb.Roles.ToList();} – Sean Newcome Feb 26 '14 at 22:34
  • @pranav rastogi plzz have a look at this UserId not found error is it a bug or issue in aspnet identity framework-----http://stackoverflow.com/questions/33455346/userid-not-found-error-in-aspnet-identity-at-generateuseridentityasync-method – neo Nov 02 '15 at 06:30
1

So if you upgrade to the 2.0.0 beta packages, you should be able to get an IQueryable of ApplicationRole directly from the role manager:

roleManager.Roles

So you don't have to drop down to the DB context, this was a limitation in 1.0 that has been fixed in the 2.0 release.

Hao Kung
  • 28,040
  • 6
  • 84
  • 93
  • Glad to see the functionality on its way. For anyone who sees this, I'm using ApplicationRole not IdentityRole because I added fields to the AspNetRoles table. If you just need to get to the Roles then you can use IdentityRole. public RoleManager RoleManager { get; private set; } – Sean Newcome Feb 27 '14 at 16:08
  • Hao why isn't the Database Context treated like any other Database Context? Have a look at http://stackoverflow.com/q/22105583/1980270 – Sean Newcome Feb 28 '14 at 21:15
  • @HaoKung i am facing some strange error. UserId not found.Plzz have a look at this stack overflow question---http://stackoverflow.com/questions/33455346/userid-not-found-error-in-aspnet-identity-at-generateuseridentityasync-method – neo Nov 02 '15 at 06:28