I'm trying to update my collection of users' roles in my ASP.NET Identity project, but I'm currently stuck because I'm getting a null UsersAndRolesDictionary
property in the ViewModel sent to my [HttpPost]
method.
Here is my ViewModel, UpdateUserRolesViewModel
:
namespace Project_Name.Models
{
public class UpdateUserRolesViewModel
{
public IDictionary<ApplicationUser, ICollection<IdentityUserRole>> UsersAndRolesDictionary { get; set; } // <-- This is returning null currently
}
}
Here's my HomeController
's methods:
[Authorize(Roles = "Admin")]
public ActionResult RoleManager()
{
ViewBag.Message = "Role Management Page";
var databaseContext = new ApplicationDbContext(); // Get the Database Context
var users = databaseContext.Users.Include(u => u.Roles); // Get all users from the Database and their Roles
var newDict = new Dictionary<ApplicationUser, ICollection<IdentityUserRole>>();
// Add each user and their roles to the dictionary
foreach (var user in users)
{
newDict.Add(user, user.Roles);
}
// Update the ViewModel with the collection of users and roles
var updateUserRolesViewModel = new UpdateUserRolesViewModel {UsersAndRolesDictionary = newDict};
return View(updateUserRolesViewModel);
}
[HttpPost]
[Authorize(Roles = "Admin")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> UpdateUsersRolesAsync(UpdateUserRolesViewModel updateUserRolesViewModel)
{
try
{
//TODO: Attempt to update the user roles or delete the user
return View("RoleManager");
}
catch
{
//TODO: Properly catch errors
return View("RoleManager");
}
}
Here is my View, RoleManager
:
@using Project_Name.Models
@model UpdateUserRolesViewModel
@{
ViewBag.Title = "Role Manager";
var databaseContext = new ApplicationDbContext(); // Get the Database Context
var roles = databaseContext.Roles; // Get all Roles from the database, use this to compare against
}
<h2>@ViewBag.Title</h2>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
@using (Html.BeginForm("UpdateUsersRolesAsync", "Home", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="form-group">
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Email</th>
<th>Roles</th>
<th>Delete User?</th>
</tr>
</thead>
<tbody>
@{
int i = 0; // Used to make unique IDs for the user's table row, and deleteUserCheckbox
int j = 0; // Used to make unique IDs for the role checkboxes
foreach (var user in Model.UsersAndRolesDictionary.Keys)
{
i++;
<tr id="userTableRow_@i">
<td>@user.Email</td>
<td>
@* Show each role availabe as a checkbox. Check them if the user has that role. *@
@foreach (var role in roles)
{
@Html.CheckBox("userRoleCheckbox_" + j++, user.Roles.Any(identityUserRole => identityUserRole.RoleId.Contains(role.Id)))
<span>@role.Name</span>
<br />
}
</td>
<td>
@Html.CheckBox("deleteUserCheckbox_" + i)
<span>Delete User</span>
</td>
</tr>
}
}
</tbody>
</table>
</div>
@* Reset and Submit buttons *@
<div class="col-lg-2 col-lg-push-8 col-md-2 col-md-push-8 col-sm-2 col-sm-push-8 col-xs-2 col-xs-push-8">
<input type="reset" class="btn btn-danger btn-block" value="Reset" />
</div>
<div class="col-lg-2 col-lg-push-8 col-md-2 col-md-push-8 col-sm-2 col-sm-push-8 col-xs-2 col-xs-push-8">
<input type="submit" class="btn btn-primary btn-block" value="Submit" />
</div>
</div>
}
</div>
</div>
I'm using the dictionary UsersAndRolesDictionary
to collect all the users and their roles, then enumerating through that to produce my view in the form of a table.
I'm hoping to change the checkbox values of potential multiple users, then passing that updated ViewModel to my [HttpPost] UpdateUsersRolesAsync
method in order to update my user roles, but right now I'm getting a null value for the UsersAndRolesDictionary
property and I'm not sure why or how to fix it.
Thanks to Stephen Muecke's links/answers in the comments I was able to answer this question. See my answer post below.