ASP.NET Core如何通过复选框批量删除记录 视图无值传回控制器问题排查
问题原因排查
- 表单结构错误:你的
</form>闭合标签写在了foreach循环内部,导致仅第一行数据在表单范围内,后续数据都不会被提交,且每次循环都会生成多余的闭合标签,DOM结构完全错误。 - 集合模型绑定规则不满足:ASP.NET Core 绑定
IEnumerable<T>类型参数时,要求表单控件的name属性必须带有索引格式(如[0].SubCategory.Id),你直接用foreach循环生成的控件name没有索引,绑定器无法识别对应集合的元素,自然无法赋值。 - 提交按钮位置错误:提交按钮放在
foreach循环内部,每一行都会生成一个删除按钮,点击任意按钮仅会提交当前行(甚至因为表单结构错误提交不到任何数据),不符合批量删除的需求。
原有逻辑修复方案
如果要保留你现有的ViewModel传递逻辑,按以下方式修改即可正常传值:
视图代码修改
@model IList<SubCategoryViewModel> <form asp-action="DeleteAll" method="post"> <table> <tr> <th> @Html.DisplayNameFor(e => e[0].SubCategory.Name) </th> <th> <input class="form-check-input" type="checkbox" id="selectAll" /> 全选 </th> </tr> @* 改用for循环生成带索引的绑定字段 *@ @for (int i = 0; i < Model.Count; i++) { <tr> <td> @Html.DisplayFor(e => e[i].SubCategory.Name) </td> <td> <input type="hidden" asp-for="@Model[i].SubCategoryCheckBox.Value" /> <input asp-for="@Model[i].SubCategoryCheckBox.Selected" /> <input type="hidden" asp-for="@Model[i].SubCategory.Id" /> </td> </tr> } @* 提交按钮移到循环外 *@ <tr> <td></td> <td> <input class="btn btn-danger" type="submit" value="批量删除" /> </td> </tr> </table> </form> @section Scripts { <script> $(document).ready(function () { // 调整选择器,避免选中全选框自身 $("#selectAll").click(function () { $("td input[type=checkbox]").prop('checked', $(this).prop('checked')); }); $("td input[type=checkbox]").click(function () { if (!$(this).prop("checked")) { $("#selectAll").prop("checked", false); } }); }); </script> }
更高效的简化实现方案
不需要传递整个ViewModel集合,仅传递选中的分类ID数组即可,减少无用数据传输,代码更简洁、性能更高:
控制器代码修改
// 直接接收选中的分类ID数组 public IActionResult DeleteAll(IEnumerable<int> selectedIds) { if (selectedIds == null || !selectedIds.Any()) { return RedirectToAction(nameof(Index)); } // EF Core 7+ 支持直接执行删除,无需先查询实体,性能更高 _db.SubCategories.Where(s => selectedIds.Contains(s.Id)).ExecuteDelete(); // 低版本EF Core用以下代码 // var delList = _db.SubCategories.Where(s => selectedIds.Contains(s.Id)).ToList(); // _db.SubCategories.RemoveRange(delList); // _db.SaveChanges(); return RedirectToAction(nameof(Index)); }
视图代码修改
@model IEnumerable<SubCategoryViewModel> <form asp-action="DeleteAll" method="post"> <table> <tr> <th> @Html.DisplayNameFor(e => e.SubCategory.Name) </th> <th> <input class="form-check-input" type="checkbox" id="selectAll" /> 全选 </th> </tr> @foreach (var subCategoryVM in Model) { <tr> <td> @Html.DisplayFor(e => subCategoryVM.SubCategory.Name) </td> <td> <!-- 复选框name统一为selectedIds,value为分类ID,选中的会自动提交到控制器参数 --> <input type="checkbox" name="selectedIds" value="@subCategoryVM.SubCategory.Id" /> </td> </tr> } <tr> <td></td> <td> <input class="btn btn-danger" type="submit" value="批量删除" /> </td> </tr> </table> </form> @section Scripts { <script> $(document).ready(function () { $("#selectAll").click(function () { $("td input[type=checkbox]").prop('checked', $(this).prop('checked')); }); $("td input[type=checkbox]").click(function () { if (!$(this).prop("checked")) { $("#selectAll").prop("checked", false); } }); }); </script> }
内容的提问来源于stack exchange,提问作者Ali Nasser
相关产品推荐
相关产品推荐

