ASP.NET中Post方法接收空模型,无法完成用户角色分配
问题:ASP.NET角色管理中提交表单后Model为空,用户无法加入角色
尝试实现给特定角色添加/移除用户的功能,勾选复选框提交表单后,用户未能成功加入目标角色,且POST方法中model.Count=0。
视图文件 EditUsersInRole.cshtml
@model List<UserRoleViewModel> @{ var roleId = ViewBag.RoleId; ViewBag.Title = "Edit Users in Role"; } <h1>Add or Romove users from this role</h1> <form asp-controller="Administration" asp-action="EditUsersInRole" method="post"> <div class="card"> <div class="card-body"> @if(Model.Count > 0) { @foreach(var user in Model) { <div class="form-check"> <input type="hidden" asp-for="@user.UserId"/> <input type="hidden" asp-for="@user.UserName"/> <input class="form-check-input" asp-for="@user.isSelected" /> <label class="form-check-label" asp-for="@user.isSelected">@user.UserName</label> </div> } } <input type="submit" value="Update" class="btn btn-primary" /> <a asp-controller="administration" asp-action="editrole" asp-route-id = "@roleId" class="btn btn-primary">Cancel</a> </div> </div> </form>
POST方法代码
[HttpPost] public async Task<IActionResult> EditUsersInRole(List<UserRoleViewModel> model, string Roleid) { if (ModelState.IsValid) { var role = await roleManager.FindByIdAsync(Roleid); if (role == null) { ViewBag.ErrorMessage = $"RoleId {Roleid} not found"; return View("NotFound"); } foreach (var item in model) { var user = await userManager.FindByIdAsync(item.UserId); var isInRole = await userManager.IsInRoleAsync(user, role.Name); IdentityResult result = null; if (item.isSelected && isInRole) { result = await userManager.AddToRoleAsync(user, role.Name); } else if (!item.isSelected && isInRole) { result = await userManager.RemoveFromRoleAsync(user, role.Name); } //if (!result.Succeeded)..... return RedirectToAction("EditRole", new {id = Roleid }); }
解决方案
1. 修复模型绑定问题(核心原因)
ASP.NET MVC无法通过foreach循环生成的表单字段绑定到List<UserRoleViewModel>,因为缺少索引标识。必须使用for循环来生成带索引的name属性,这样表单提交时才能正确映射到集合参数。
修改后的视图代码:
@model List<UserRoleViewModel> @{ var roleId = ViewBag.RoleId; ViewBag.Title = "Edit Users in Role"; } <h1>Add or Remove users from this role</h1> <form asp-controller="Administration" asp-action="EditUsersInRole" method="post"> <div class="card"> <div class="card-body"> @if(Model.Count > 0) { @for (int i = 0; i < Model.Count; i++) { <div class="form-check"> <input type="hidden" asp-for="@Model[i].UserId"/> <input type="hidden" asp-for="@Model[i].UserName"/> <input class="form-check-input" asp-for="@Model[i].isSelected" /> <label class="form-check-label" asp-for="@Model[i].isSelected">@Model[i].UserName</label> </div> } } <!-- 新增隐藏字段传递Roleid,否则POST方法中Roleid会为null --> <input type="hidden" name="Roleid" value="@roleId" /> <input type="submit" value="Update" class="btn btn-primary" /> <a asp-controller="administration" asp-action="editrole" asp-route-id = "@roleId" class="btn btn-primary">Cancel</a> </div> </div> </form>
2. 修复POST方法的逻辑错误
return语句放在了foreach循环内部,导致循环仅执行一次就跳转,后续用户的角色变更逻辑不会执行,需要将return移到循环外部。- 原逻辑中
item.isSelected && isInRole的判断错误:应该是选中且用户不在角色中时添加,否则会重复添加。 - 增加用户空判断,避免空引用异常;添加结果失败的处理逻辑。
修改后的POST方法:
[HttpPost] public async Task<IActionResult> EditUsersInRole(List<UserRoleViewModel> model, string Roleid) { if (ModelState.IsValid) { var role = await roleManager.FindByIdAsync(Roleid); if (role == null) { ViewBag.ErrorMessage = $"RoleId {Roleid} not found"; return View("NotFound"); } foreach (var item in model) { var user = await userManager.FindByIdAsync(item.UserId); if (user == null) continue; // 跳过不存在的用户 var isInRole = await userManager.IsInRoleAsync(user, role.Name); IdentityResult result = null; // 修正逻辑:选中且不在角色 → 添加;未选中且在角色 → 移除 if (item.isSelected && !isInRole) { result = await userManager.AddToRoleAsync(user, role.Name); } else if (!item.isSelected && isInRole) { result = await userManager.RemoveFromRoleAsync(user, role.Name); } // 处理角色变更失败的情况 if (result != null && !result.Succeeded) { foreach (var error in result.Errors) { ModelState.AddModelError("", error.Description); } return View(model); // 返回视图显示错误信息 } } // 所有用户处理完成后再跳转 return RedirectToAction("EditRole", new { id = Roleid }); } // 模型验证失败时返回原视图 return View(model); }
内容的提问来源于stack exchange,提问作者Nora
相关产品推荐
相关产品推荐

