我正在尝试更新我的 ASP.NET Identity项目中的用户角色集合,但我目前陷入困境,因为我在发送到我的[HttpPost]
方法的ViewModel中获得了一个空UsersAndRolesDictionary
属性。
这是我的观点模型,UpdateUserRolesViewModel
:
namespace Project_Name.Models
{
public class UpdateUserRolesViewModel
{
public IDictionary<ApplicationUser, ICollection<IdentityUserRole>> UsersAndRolesDictionary { get; set; } // <-- This is returning null currently
}
}
这是我HomeController
的方法:
[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");
}
}
这是我的观点,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>
我正在使用字典UsersAndRolesDictionary
来收集所有用户及其角色,然后枚举以表格的形式生成我的视图。
我希望更改潜在多个用户的复选框值,然后将更新的 ViewModel 传递给我的 [HttpPost] UpdateUsersRolesAsync
方法以更新我的用户角色,但现在我得到了 UsersAndRolesDictionary
属性的空值,我不确定为什么或如何修复它。
感谢斯蒂芬·穆克在评论中的链接/答案,我能够回答这个问题。请参阅下面的回答帖子。
按照 Stephen Muecke 在评论中的建议,我得到了一个有效的 ViewModel 要返回。
添加/更新了三个组合在一起的视图模型:
首先是RoleViewModel
:
public class RoleViewModel
{
public string Id { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
第二UserViewModel
:
public class UserViewModel
{
public string Id { get; set; }
public string Email { get; set; }
public List<RoleViewModel> RoleViewModels { get; set; }
public bool DeleteUser { get; set; } // Doesn't work yet, might be in the wrong place
}
最后第三个是UpdateUserRoleViewModel
的更新版本:
public class UpdateUserRolesViewModel
{
public int Id { get; set; }
public List<UserViewModel> UserViewModels { get; set; }
}
在我的更新HomeController
中,再次是方法:
[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).ToList(); // Get all users from the Database and their Roles
// Create the UpdateUserRolesViewModel
var updateUserRolesViewModel = new UpdateUserRolesViewModel
{
Id = 0, // Not sure what else the Id would be
UserViewModels = new List<UserViewModel>()
};
// Add each user to the UserViewModels list
for (int i = 0; i < users.Count(); i++)
{
var userViewModel = new UserViewModel
{
Id = users.AsEnumerable().ElementAt(i).Id,
Email = users.AsEnumerable().ElementAt(i).UserName,
RoleViewModels = new List<RoleViewModel>(),
DeleteUser = false
};
// Add each role from the Roles table to the RoleViewModels list, check if user has that role
foreach (var role in databaseContext.Roles)
{
var roleViewModel = new RoleViewModel
{
Id = role.Id,
Name = role.Name,
IsSelected = users.AsEnumerable().ElementAt(i).Roles.Any(identityUserRole => identityUserRole.RoleId.Contains(role.Id))
};
userViewModel.RoleViewModels.Add(roleViewModel);
}
updateUserRolesViewModel.UserViewModels.Add(userViewModel);
}
return View(updateUserRolesViewModel);
}
[HttpPost]
[Authorize(Roles = "Admin")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> UpdateUsersRolesAsync(UpdateUserRolesViewModel updateUserRolesViewModel)
{
try
{
// Attempt to update the user roles
foreach (var user in updateUserRolesViewModel.UserViewModels)
{
// Delete user
//TODO: Prompt user to confirm deletion if one or more people are being deleted
if (user.DeleteUser)
{
var userToDelete = await UserManager.FindByIdAsync(user.Id); // Get the ApplicationUser object of who we want to delete
await UserManager.DeleteAsync(userToDelete); // Delete the user
continue; // Don't try to update the roles of a deleted user.
}
// Remove all roles from the User
var rolesToRemove = await UserManager.GetRolesAsync(user.Id);
await UserManager.RemoveFromRolesAsync(user.Id, rolesToRemove.ToArray());
// Add roles to the User
foreach (var roleViewModel in user.RoleViewModels.Where(r => r.IsSelected))
{
await UserManager.AddToRoleAsync(user.Id, roleViewModel.Name);
}
}
return RedirectToAction("RoleManager");
}
catch
{
//TODO: Properly catch errors
return RedirectToAction("RoleManager");
}
}
最后,这是我的观点,角色经理
@using Project_Name.ViewModels
@model UpdateUserRolesViewModel
@{
ViewBag.Title = "Role Manager";
}
@* Debugging text *@
@foreach (var user in Model.UserViewModels)
{
<div>User ID: @user.Id</div>
<div>User Name: @user.Email</div>
<p>
@foreach (var roleViewModel in user.RoleViewModels.Where(r => r.IsSelected))
{
<div>Role ID: @roleViewModel.Id</div>
<div>Role Name: @roleViewModel.Name</div>
}
</p>
<hr />
}
<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()
@Html.HiddenFor(m => m.Id)
<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>
@for (int i = 0; i < Model.UserViewModels.Count; i++)
{
<tr id="userTableRow_@i">
<td>
@Html.HiddenFor(m => m.UserViewModels[i].Id)
@Html.HiddenFor(m => m.UserViewModels[i].Email)
@Model.UserViewModels[i].Email
</td>
<td>
@for (int j = 0; j < Model.UserViewModels[i].RoleViewModels.Count; j++)
{
@Html.HiddenFor(m => m.UserViewModels[i].RoleViewModels[j].Id)
@Html.HiddenFor(m => m.UserViewModels[i].RoleViewModels[j].Name)
@Html.CheckBoxFor(m => m.UserViewModels[i].RoleViewModels[j].IsSelected)
@Html.DisplayTextFor(m => m.UserViewModels[i].RoleViewModels[j].Name)
<br/>
}
</td>
<td>
@Html.CheckBoxFor(m => m.UserViewModels[i].DeleteUser)
@Html.DisplayNameFor(m => m.UserViewModels[i].DeleteUser)
</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>
现在,这会更新用户的角色,并删除它们(尽管没有确认检查,所以要小心!