Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

Add or remove users from role in asp.net core

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


asp.net core identity add user to role

<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.

asp.net core identity remove user from role

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.

asp.net core 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 EditUsersInRole Action

[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>

asp.net core tutorial for beginners

12 comments:

  1. It's more readable (clean).

    var 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;
    //}

    ReplyDelete
  2. 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

    ReplyDelete
  3. When 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 ?

    ReplyDelete
    Replies
    1. in UserRoleViewModel
      add this
      public string RoleId { get; set; }


      and donot forget
      in EditUsersInRole to add
      @{
      var roleId = ViewBag.roleId;
      }

      Delete
    2. 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

      Delete
  4. hi
    I 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?

    ReplyDelete
  5. 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.

    ReplyDelete
  6. If 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.
    Ex: "EmployeeDBConnection": "server=(localdb)\\MSSQLLocalDB;database=EmployeeDB;Trusted_Connection=true;MultipleActiveResultSets=True"

    ReplyDelete
  7. Hi, i have a question.
    Is "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?

    ReplyDelete
  8. Please all if your using Core3.0
    to use
    userManager.Users.ToList()
    instead of userManager.users
    Regards...
    Adham.

    ReplyDelete
  9. 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?

    ReplyDelete
  10. always return List model empty any one know why ?

    ReplyDelete

It would be great if you can help share these free resources