ASP.NET Core MVC如何将选中复选框的完整模型传递到控制器
ASP.NET Core MVC 复选框提交完整模型解决方案
问题根源
HTTP 表单默认仅支持提交键值对格式的数据,你当前的写法只将单个字段设置为复选框的value,后端不可能自动拿到包含全部字段的SomeType1对象。同时你后端接收的List<SomeType1>参数不符合ASP.NET Core MVC的复杂集合模型绑定规则,无法正确解析数据。
方案1:常规实现(推荐,性能高、符合开发规范)
这类场景不需要提交全量字段,仅需提交选中项的唯一标识(Id/Value),后端再根据标识匹配全量对象即可,避免数据冗余和篡改风险。
1. 调整视图代码
将复选框的name统一设置为接收参数名,value设置为唯一标识Id:
@foreach (var item in Model.SomeModel.SomeType1) { <b>Some Type 1</b> <div class="checkbox"> <label> <input type="checkbox" name="selectedSomeType1Ids" value="@item.Id" /> @item.Name </label> </div> } @foreach (var item in Model.SomeModel.SomeOtherType2) { <b>SomeOtherType2</b> <div class="checkbox"> <label> <input type="checkbox" name="selectedSomeOtherType2Ids" value="@item.Id" /> @item.Name </label> </div> }
2. 调整后端POST方法
先获取全量数据源,再根据选中的Id筛选出完整对象:
[HttpPost] public IActionResult Index(string search, List<string> selectedSomeType1Ids, List<string> selectedSomeOtherType2Ids) { // 构造全量数据源,实际开发中如果是动态数据可从数据库/缓存查询,静态数据可封装为公共方法复用 var allSomeType1 = new List<SomeType1> { new SomeType1 { Id = "1", Name = "Spinach", Value = "TXT_FLD_SPINA", ExtraInfo = "something1" }, new SomeType1 { Id = "2", Name = "Broccoli", Value = "TXT_FLD_BRO", ExtraInfo = "something else5" }, new SomeType1 { Id = "3", Name = "Wheatgrass", Value = "TXT_FLD_WHE", ExtraInfo = "something else4" }, }; var allSomeOtherType2 = new List<SomeType1> { new SomeType1 { Id = "1", Name = "Apple", Value = "TXT_FLD_APPLE", ExtraInfo = "something" }, new SomeType1 { Id = "2", Name = "Banana", Value = "TXT_FLD_BANA", ExtraInfo = "something else" }, new SomeType1 { Id = "3", Name = "Tomatoes", Value = "TXT_FLD_TOM", ExtraInfo = "something else2" }, }; // 筛选出选中的完整对象 var selectedSomeType1 = allSomeType1.Where(x => selectedSomeType1Ids?.Contains(x.Id) == true).ToList(); var selectedSomeOtherType2 = allSomeOtherType2.Where(x => selectedSomeOtherType2Ids?.Contains(x.Id) == true).ToList(); // 后续业务逻辑处理 return View(); }
方案2:直接提交完整对象(不推荐,仅适用特殊场景)
如果业务要求必须前端直接提交全量字段,可通过ASP.NET Core的索引绑定规则,配合隐藏域实现全字段提交:
1. 调整视图代码
将foreach改为带索引的for循环,为每个字段添加绑定,非标识字段用隐藏域存储:
@using (Html.BeginForm("Index", "Home")) { <div class="text-center"> <input type="text" name="search" /> <input type="submit" value="Submit" /> </div> <br /> @for (int i = 0; i < Model.SomeModel.SomeType1.Count; i++) { <b>Some Type 1</b> <div class="checkbox"> <label> <input type="checkbox" name="SomeModel.SomeType1[@i].Id" value="@Model.SomeModel.SomeType1[i].Id" /> @Model.SomeModel.SomeType1[i].Name <input type="hidden" name="SomeModel.SomeType1[@i].Name" value="@Model.SomeModel.SomeType1[i].Name" /> <input type="hidden" name="SomeModel.SomeType1[@i].Value" value="@Model.SomeModel.SomeType1[i].Value" /> <input type="hidden" name="SomeModel.SomeType1[@i].ExtraInfo" value="@Model.SomeModel.SomeType1[i].ExtraInfo" /> </label> </div> } @for (int i = 0; i < Model.SomeModel.SomeOtherType2.Count; i++) { <b>SomeOtherType2</b> <div class="checkbox"> <label> <input type="checkbox" name="SomeModel.SomeOtherType2[@i].Id" value="@Model.SomeModel.SomeOtherType2[i].Id" /> @Model.SomeModel.SomeOtherType2[i].Name <input type="hidden" name="SomeModel.SomeOtherType2[@i].Name" value="@Model.SomeModel.SomeOtherType2[i].Name" /> <input type="hidden" name="SomeModel.SomeOtherType2[@i].Value" value="@Model.SomeModel.SomeOtherType2[i].Value" /> <input type="hidden" name="SomeModel.SomeOtherType2[@i].ExtraInfo" value="@Model.SomeModel.SomeOtherType2[i].ExtraInfo" /> </label> </div> } }
2. 调整后端POST方法
直接接收视图模型,过滤掉未选中的项即可:
[HttpPost] public IActionResult Index(string search, MainViewModel model) { // 未勾选的项Id不会提交,过滤空Id即可得到选中的完整对象 var selectedSomeType1 = model.SomeModel.SomeType1.Where(x => !string.IsNullOrEmpty(x.Id)).ToList(); var selectedSomeOtherType2 = model.SomeModel.SomeOtherType2.Where(x => !string.IsNullOrEmpty(x.Id)).ToList(); // 后续业务逻辑处理 return View(model); }
注意使用该方案需要保证MainViewModel、SomeModel的构造函数已经初始化了对应的List<SomeType1>属性,避免绑定失败。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

