Suggested Videos
Part 78 - Creating roles in asp.net core | Text | Slides
Part 79 - Get list of roles in asp.net core | Text | Slides
Part 80 - Edit role in asp.net core | Text | Slides
In this video we will discuss how to manage role membership i.e add or remove users from a given role using the asp.net core identity api.
On Edit role view, when Add or remove users from this role button is clicked, we want to redirect to Edit users in role view
Edit users in role view is as shown below. If you want the user to be a member of the given role, check the checkbox, otherwise leave it unchecked.
Once the Update button is clicked the data should be updated in the underlying AspNetUserRoles database table.
AspNetUserRoles identity database table
Application users are stored in AspNetUsers database table, where as roles are stored in AspNetRoles table. UserRoles i.e user to role mapping data is stored in AspNetUserRoles table.
There is a Many-to-Many relationship between AspNetUsers and AspNetRoles table. A user can be a member of many roles and a role can contain many users as it's members. This User and Role mapping data is stored in AspNetUserRoles table.
This table has just 2 columns - UserId and RoleId. Both are foreign keys. UserId column references Id column in AspNetUsers table and RoleId column references Id column in AspNetRoles table.
UserRoleViewModel Class
HttpPost EditUsersInRole Action
EditUsersInRole View
Part 78 - Creating roles in asp.net core | Text | Slides
Part 79 - Get list of roles in asp.net core | Text | Slides
Part 80 - Edit role in asp.net core | Text | Slides
In this video we will discuss how to manage role membership i.e add or remove users from a given role using the asp.net core identity api.
On Edit role view, when Add or remove users from this role button is clicked, we want to redirect to Edit users in role view
<div class="card-footer">
<a asp-controller="Administration" asp-action="EditUsersInRole"
asp-route-roleId="@Model.Id" class="btn btn-primary">
Add or remove users from this role
</a>
</div>
Edit users in role view is as shown below. If you want the user to be a member of the given role, check the checkbox, otherwise leave it unchecked.
Once the Update button is clicked the data should be updated in the underlying AspNetUserRoles database table.
AspNetUserRoles identity database table
Application users are stored in AspNetUsers database table, where as roles are stored in AspNetRoles table. UserRoles i.e user to role mapping data is stored in AspNetUserRoles table.
There is a Many-to-Many relationship between AspNetUsers and AspNetRoles table. A user can be a member of many roles and a role can contain many users as it's members. This User and Role mapping data is stored in AspNetUserRoles table.
This table has just 2 columns - UserId and RoleId. Both are foreign keys. UserId column references Id column in AspNetUsers table and RoleId column references Id column in AspNetRoles table.
UserRoleViewModel Class
public class UserRoleViewModel
{
public string UserId {
get; set; }
public string UserName
{ get; set; }
public bool
IsSelected { get; set; }
}
- In the UserRoleViewModel class, in addition to UserId property, we have UserName and IsSelected properties.
- UserName property is required so we can display the UserName on the view.
- IsSelected property is required to determine if the user is selected to be a member of the role.
- We could include RoleId property also in the UserRoleViewModel class, but as far as this view is concerned, there is a one-to-many relationship from Role to Users. So, in order not to repeat RoleId for each User, we will use ViewBag to pass RoleId from controller to the view.
[HttpGet]
public async
Task<IActionResult> EditUsersInRole(string roleId)
{
ViewBag.roleId = roleId;
var role = await
roleManager.FindByIdAsync(roleId);
if (role == null)
{
ViewBag.ErrorMessage = $"Role with Id = {roleId} cannot be found";
return View("NotFound");
}
var model = new
List<UserRoleViewModel>();
foreach (var user in userManager.Users)
{
var userRoleViewModel = new UserRoleViewModel
{
UserId = user.Id,
UserName = user.UserName
};
if (await
userManager.IsInRoleAsync(user, role.Name))
{
userRoleViewModel.IsSelected = true;
}
else
{
userRoleViewModel.IsSelected = false;
}
model.Add(userRoleViewModel);
}
return View(model);
}
HttpPost EditUsersInRole Action
[HttpPost]
public async
Task<IActionResult> EditUsersInRole(List<UserRoleViewModel> model, string roleId)
{
var role = await
roleManager.FindByIdAsync(roleId);
if (role == null)
{
ViewBag.ErrorMessage = $"Role with Id = {roleId} cannot be found";
return View("NotFound");
}
for (int i = 0; i
< model.Count; i++)
{
var user = await
userManager.FindByIdAsync(model[i].UserId);
IdentityResult result = null;
if (model[i].IsSelected && !(await userManager.IsInRoleAsync(user, role.Name)))
{
result = await userManager.AddToRoleAsync(user,
role.Name);
}
else if
(!model[i].IsSelected && await userManager.IsInRoleAsync(user, role.Name))
{
result = await
userManager.RemoveFromRoleAsync(user, role.Name);
}
else
{
continue;
}
if (result.Succeeded)
{
if (i < (model.Count - 1))
continue;
else
return RedirectToAction("EditRole", new { Id =
roleId });
}
}
return RedirectToAction("EditRole", new { Id =
roleId });
}
EditUsersInRole View
@model
List<UserRoleViewModel>
@{
var roleId = ViewBag.roleId;
}
<form method="post">
<div class="card">
<div class="card-header">
<h2>Add or
remove users from this role</h2>
</div>
<div class="card-body">
@for (int i = 0; i
< Model.Count; i++)
{
<div class="form-check m-1">
<input type="hidden" asp-for="@Model[i].UserId" />
<input type="hidden" asp-for="@Model[i].UserName" />
<input asp-for="@Model[i].IsSelected" class="form-check-input" />
<label class="form-check-label" asp-for="@Model[i].IsSelected">
@Model[i].UserName
</label>
</div>
}
</div>
<div class="card-footer">
<input type="submit" value="Update" class="btn
btn-primary"
style="width:auto" />
<a asp-action="EditRole" asp-route-id="@roleId"
class="btn btn-primary" style="width:auto">Cancel</a>
</div>
</div>
</form>
It's more readable (clean).
ReplyDeletevar userRoleViewModel = new UserRoleViewModel
{
UserId = user.Id,
UserName = user.UserName,
IsSelected = await userManager.IsInRoleAsync(user, role.Name)
};
//if (await userManager.IsInRoleAsync(user, role.Name))
//{
// userRoleViewModel.IsSelected = true;
//}
//else
//{
// userRoleViewModel.IsSelected = false;
//}
Thank you for providing this code! I had a small error in my markup and could not find it anywhere, this saved me hours of searching. Thanks again
ReplyDeleteWhen i copy paste this code, my method doesn't get roleId in EditUsersInRole, and if it works on your machine how does that roleId has been past from view ?
ReplyDeletein UserRoleViewModel
Deleteadd this
public string RoleId { get; set; }
and donot forget
in EditUsersInRole to add
@{
var roleId = ViewBag.roleId;
}
I did all these sir, I have done all I could... Yet I couldn't ADD users to the role.. and am stuck. The roleid at EditUserInRole keeps Returning null.. please what can I do to resolve this... Am very helpless now. Thanks
DeleteHow did you resolve the "null" error and added users to roles?
Deletehi
ReplyDeleteI changed th get method to ths
foreach (var user in userManager.Users.ToList())
now I face error when I run project. UserId and userName are null inthe model.
how could I fix?
If anyone has got a NULL problem with ViewBag.RoleId, I got it fixed by changing the string to "Id" (public async Task EditUsersInRole(string Id)) for both Get and Post. Don't know if this is the right solution but it works fine.
ReplyDeleteIf you are getting "InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first." error, add "MultipleActiveResultSets=True" in EmployeeDB Connection, and then restart your debugging.
ReplyDeleteEx: "EmployeeDBConnection": "server=(localdb)\\MSSQLLocalDB;database=EmployeeDB;Trusted_Connection=true;MultipleActiveResultSets=True"
Hi, i have a question.
ReplyDeleteIs "if (result.Succeeded)" never gonna throw a NullReferenceException when you edit a role with no users assigned to it, and you do not select any users from the list, then click on update button? Or is the NullReferenceException on "if (result.Succeeded)" ignored because it is not gonna hit it inside the for loop?
Please all if your using Core3.0
ReplyDeleteto use
userManager.Users.ToList()
instead of userManager.users
Regards...
Adham.
I have a problem with passing the object list from view to controller, its always null for me, are there any other ways that i can pass that list?
ReplyDeletealways return List model empty any one know why ?
ReplyDeleteUse for loop instead of for each loop.
Deletefor more info watch 92 part of asp.net core video series by venkat sir
@Destech, please how did you resolve the "null" error and added users to roles?
ReplyDelete