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):
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:
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
Show activity on this post. var user = await _userManager. FindByIdAsync(UserId); var roles = await _userManager. GetRolesAsync(user); return OK(new { User = user, Roles = roles });
You can get the list of users assigned to role ID by following below steps: Navigate to System Admin -> Security -> Role Management -> Search for the role you want the details and click on edit icon -> Go to Users Tab. The users tab will show all the users or admin details who are assigned to that particular role.
ASP.NET Core Identity: Is an API that supports user interface (UI) login functionality. Manages users, passwords, profile data, roles, claims, tokens, email confirmation, and more.
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
.
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()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With