You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 15:54:55