ASP.NET MVC 无法 POST 绑定到复选框的视图模型

ASP.NET MVC cannot POST view model with binding to checkbox

这是我的视图模型:

public class UserViewModel
{
    public User GroupUser { get; set; }
    public bool Checked { get; set; }
}

public class GroupUserViewModel
{
    public Guid GroupId { get; set; }
    public string GroupName { get; set; }
    public IList<UserViewModel> Users;        
}

我的看法:

@model GroupUserViewModel

@{
    ViewBag.Title = "Users";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>@Model.GroupName</h2>

@using (Html.BeginForm("AddUserToGroup", "Group", FormMethod.Post))
{
    for (var userIter = 0; userIter < Model.Users.Count(); userIter++)
    {
        <div class="form-group">
            @Html.DisplayFor(model => model.Users[userIter].GroupUser.UserName)
            @Html.CheckBoxFor(model => model.Users[userIter].Checked)

            @Html.HiddenFor(model => model.GroupId)
            @Html.HiddenFor(model => model.GroupName)
        </div>        
    }

    <input type="submit" class="btn btn-success" value="Save"/>
}

我的控制器:

[HttpPost]
public ActionResult AddUserToGroup(GroupUserViewModel groupUsers)
{
    //do things    
}

我检查了 POST 数据,它是:

Users[0].Checked=true
Users[0].Checked=false
Users[1].Checked=false

对于我勾选的方框,有 2 个条目,一个 true 和一个 false。这正常吗?

同样在控制器中,我得到的是:

groupUsers.GroupId = {00000000-0000-0000-0000-000000000000}
groupUsers.GroupName = null
groupUsers.Users = null

显然,由于表单实际上并未将我想要的视图模型发布回控制器,因此发生了这种情况。有什么方法可以将所需的视图模型传递回控制器,因为我需要 GroupIdGroupName?

编辑:

经过一些更新并添加 GroupIdGroupName 的隐藏字段后,现在 POST 数据为:

Users[0].Checked=true
Users[0].Checked=false
Id=015f5aef-eb6c-449e-9f08-9d42110c5347
GroupName=MyName
MyObjects[1].Checked=false
Id=015f5aef-eb6c-449e-9f08-9d42110c5347
GroupName=MyName

GroupIdGroupName 现在正在正确传递,但列表仍然是 null

是的,这很正常。原因是因为未选中的复选框不会 post 值,因此 ASP.NET 为每个具有与复选框控件后面的复选框相同 ID 的复选框呈现一个隐藏字段,并将其值设置为 false。 ASP.NET 如果有多个同名表单字段,DefaultModelBinder 将取第一个值。如果未选中该复选框,这会导致从隐藏字段 post 编辑一个 false 值,以及两个值,一个 false 用于隐藏字段,一个 true 用于选中的复选框。因为隐藏字段在复选框之后,如果复选框 post 是一个值,它将覆盖隐藏字段。 但是,这并没有回答您关于模型为何不具有约束力的问题..

GroupUserViewModel 中的

IList<UserViewModel> Users 是一个字段,而不是 属性,因此 DefaultModelBinder 无法设置其值。改成

public class GroupUserViewModel
{
    ....
    public IList<UserViewModel> Users { get; set; } // make it a property   
}