ASP.Net Core how to get the user role in EF Core and Identity

20,269

Solution 1

var user = await _userManager.FindByIdAsync(UserId);
var roles = await _userManager.GetRolesAsync(user);

return OK(new { User = user, Roles = roles });

This produces role names, either way the only way to get this back to your api call is to return a ViewModel or other option as Chris points out it isn't possible to directly call.. Its so round about to achieve something so small.

At any rate this is a second option to get the "Role" names without having to touch your db context.

If you want the Id's pull that from RoleManager<IdentityRole> or tap your dbcontext.

Callings it Roles in what ever you do might cause interference since roles[] will already exist in the return of the User.

Solution 2

Unfortunately, there's not navigation properties on UserRole, so it's a manual affair. You'd need to do something like:

var userRoleIds = user.Roles.Select(r => r.RoleId);
var roles = db.Roles.Where(r => userRoleIds.Contains(r.Id));

Then, you can map those on to the user via a view model. For example:

public class UserViewModel
{
    ...
    public List<string> Roles { get; set; }
}

Then:

var model = new UserViewModel
{
    ...
    Roles = roles.Select(r => r.Name).ToList()
}
Share:
20,269
Angel Silva
Author by

Angel Silva

Updated on August 02, 2020

Comments

  • Angel Silva
    Angel Silva over 3 years

    Hi I'm building a API using Identity with a custom user class,and EF Core. I want to get the name of the role that belongs to an user. The diagram of the tables is the following(ignore userclaims and userlogins): enter image description here

    As you can see the Roles and Users is N to N so internally Identity made a junction table named UserRoles, my contoller looks like this:

    Route ("api/[controller]")]
        public class UserController : Controller {
            private readonly DBContext _db;
            private readonly UserManager<Usuario> _userManager;
            public UserController (DBContext db, UserManager<Usuario> userManager) {
                this._db = db;
            }
            [HttpGet ("GetUserById/{id}", Name = "GetUserById")]
            public async Task<IActionResult> GetUserById (string id) {
                try {
    
                    var user = await this._db.Users.Where (x => x.Id == id).Include (x => x.Roles).FirstOrDefaultAsync ();
                    if (user == null) {
                        return NotFound ();
                    }
                    return Ok (user);
                } catch (Exception e) {
                    Console.WriteLine (e.Message);
                    return BadRequest ();
                }
            }
    

    When I called it in Postman I get the following response:

    enter image description here

    As you can see in the roles part all I get is:

    "roles": [
            {
                "userId": "d88b0c2d-25c5-4da9-ad05-45f69dec67ff",
                "roleId": "a83a60ca-f011-43ce-be3d-8b71403aa86e"
            }
        ]
    

    That data belongs to the junction table not the Role table itself, I dont want that.

    What I really want is the "real" Role table data, Any idea how can I achieve that?

    In sql it would be something like :

    select *
        from AspNetUsers as a,AspNetUserRoles as b,AspNetRoles as c 
        where a.Id = b.UserId and b.RoleId= c.Id