.NET 7.0 MVC批量删除选中项时Controller参数为空求助
.NET 7.0 MVC批量删除功能参数为空问题解决
问题描述
在.NET 7.0 MVC项目中,通过Controller从Web API获取Material列表并传递到View展示,想要实现批量删除复选框选中项的功能,但调用Controller的StartProcedure方法时,传入的List<Material>参数始终为空,尝试修改参数类型为List<object>或object仍无法解决。
原代码展示
1. Controller传递列表至View的代码
try { List<Material> MaterialInfo = new List<Material>(); using (var client = new HttpClient()) { client.BaseAddress = new Uri(Baseurl); client.DefaultRequestHeaders.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage Res = await client.GetAsync("api/Materials"); if (Res.IsSuccessStatusCode) { var MaterialsResponse = Res.Content.ReadAsStringAsync().Result; MaterialInfo = JsonConvert.DeserializeObject<List<Material>>(MaterialsResponse); CurrentMaterials.Add(MaterialInfo); } return View(MaterialInfo); } } catch (Exception) { return View(); }
2. 接收参数的Controller方法
[HttpPost] public ActionResult StartProcedure(List<Material> materials) { try { //foreach (var item in materials) //{ //} return View(); } catch (Exception ex) { return View(); } }
3. View展示及表单代码
<tbody> @using (Html.BeginForm("StartProcedure", "LastedStatus", FormMethod.Post)) { @foreach (var material in Model) { @if(material.CabinStatus == CabinStatus.outCabin) { <tr> <td> @Html.CheckBoxFor(r => material.isSelected, new { @class = "checkbox" }) </td> <td> @Html.DisplayFor(modelItem => material.Id) </td> <td> @Html.DisplayFor(modelItem => material.Code) </td> <td> @Html.DisplayFor(modelItem => material.Name) </td> <td> @Html.DisplayFor(modelItem => material.Description) </td> <td> @Html.DisplayFor(modelItem => material.BatchNumber) </td> <td> @Html.DisplayFor(modelItem => material.RfId) </td> <td> @Html.DisplayFor(modelItem => material.Weight) </td> <td> @Html.DisplayFor(modelItem => material.MaterialDrawerNo) </td> <td> @Html.DisplayFor(modelItem => material.MaterialLocation_X) </td> <td> @Html.DisplayFor(modelItem => material.MaterialLocation_Y) </td> <td> @Html.DisplayFor(modelItem => material.RemainingTime) </td> <td> @Html.DisplayFor(modelItem => material.PickUpTime) </td> <td> @Html.DisplayFor(modelItem => material.OutsideTime) </td> <td> @Html.DisplayFor(modelItem => material.CabinStatus) </td> <td> @Html.DisplayFor(modelItem => material.TimeAlarm) </td> <td> @Html.DisplayFor(modelItem => material.LifeEnding) </td> <td> @Html.DisplayFor(modelItem => material.TimeProcess) </td> </tr> } } <input type="button" id="deleteItems" value="Delete Selected Items" name="Verify Order Information" class="btn btn-primary btn-large" /> } </tbody>
4. AJAX提交代码(第一种尝试)
@section scripts{ <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script type="text/javascript" src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script> <script type="text/javascript"> $("body").on("click", "#deleteItems", function () { //Loop through the Table rows and build a JSON array. var materials = new Array(); $("#table BODY TR").each(function () { var row = $(this); var material = {}; material.isSelected = row.find("td:eq(0)").html(); material.Id = row.find("td:eq(1)").html(); material.Code = row.find("td:eq(2)").html(); material.Name = row.find("td:eq(3)").html(); material.Description = row.find("td:eq(4)").html(); material.BatchNumber = row.find("td:eq(5)").html(); material.RfId = row.find("td:eq(6)").html(); material.Weight = row.find("td:eq(7)").html(); material.MaterialDrawerNo = row.find("td:eq(8)").html(); material.MaterialLocation_X = row.find("td:eq(9)").html(); material.MaterialLocation_Y = row.find("td:eq(10)").html(); material.RemainingTime = row.find("td:eq(0)").html(); material.PickUpTime = row.find("td:eq(11)").html(); material.OutsideTime = row.find("td:eq(12)").html(); material.CabinStatus = row.find("td:eq(13)").html(); material.TimeAlarm = row.find("td:eq(14)").html(); material.LifeEnding = row.find("td:eq(15)").html(); material.TimeProcess = row.find("td:eq(16)").html(); materials.push(material); }); //Send the JSON array to Controller using AJAX. $.ajax({ type: "POST", url: "/LastedStatus/StartProcedure", data: JSON.stringify(materials), contentType: "application/json; charset=utf-8", dataType: "json", success: function (r) { alert(r + " Success."); } }); }); </script> }
5. AJAX提交代码(第二种尝试)
@section scripts{ <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script type="text/javascript" src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script> <script type="text/javascript"> $("body").on("click", "#deleteItems", function () { //Loop through the Table rows and build a JSON array. var materials = new Array(); $("#table BODY TR").each(function () { var row = $(this).closest("tr"); var material = {}; material.isSelected = row.find("TD").eq(0).html(); material.Id = row.find("TD").eq(1).html(); material.Code = row.find("TD").eq(2).html(); material.Name = row.find("TD").eq(3).html(); material.Description = row.find("TD").eq(4).html(); material.BatchNumber = row.find("TD").eq(5).html(); material.RfId = row.find("TD").eq(6).html(); material.Weight = row.find("TD").eq(7).html(); material.MaterialDrawerNo = row.find("TD").eq(8).html(); material.MaterialLocation_X = row.find("TD").eq(9).html(); material.MaterialLocation_Y = row.find("TD").eq(10).html(); material.RemainingTime = row.find("TD").eq(11).html(); material.PickUpTime = row.find("TD").eq(12).html(); material.OutsideTime = row.find("TD").eq(13).html(); material.CabinStatus = row.find("TD").eq(14).html(); material.TimeAlarm = row.find("TD").eq(15).html(); material.LifeEnding = row.find("TD").eq(16).html(); material.TimeProcess = row.find("TD").eq(17).html(); materials.push(material); }); //Send the JSON array to Controller using AJAX. $.ajax({ type: "POST", url: "/LastedStatus/StartProcedure2", data: JSON.stringify(materials), contentType: "application/json; charset=utf-8", dataType: "json", success: function (r) { alert(r + " Success."); } }); }); </script> }
问题原因及解决方案
核心问题分析
- Model绑定命名错误:
foreach循环生成的input标签没有带索引的命名(如[0].isSelected),MVC无法识别为列表格式,导致参数绑定失败。 - AJAX提交逻辑错误:
- 未筛选选中的行,而是遍历所有行;
- 获取复选框状态用
html()错误,应使用prop("checked")获取布尔值; - 部分字段索引错误(如第一种AJAX中
RemainingTime重复使用了eq(0));
- Controller未指定JSON解析方式:提交的JSON数据在请求体中,需添加
[FromBody]特性告诉MVC从请求体解析参数。
修正后的代码
1. 修正Controller接收方法
[HttpPost] public ActionResult StartProcedure([FromBody] List<Material> materials) { try { // 筛选出选中的项 var selectedItems = materials.Where(m => m.isSelected).ToList(); // 执行删除逻辑 return Json(new { success = true, count = selectedItems.Count }); } catch (Exception ex) { return Json(new { success = false, message = ex.Message }); } }
2. 修正View的循环逻辑(改用for循环生成正确的命名)
@model List<Material> <tbody> @using (Html.BeginForm()) { @for (int i = 0; i < Model.Count; i++) { if(Model[i].CabinStatus == CabinStatus.outCabin) { <tr> <td> @Html.CheckBoxFor(m => m[i].isSelected, new { @class = "checkbox" }) <!-- 隐藏字段存储需要提交的属性值 --> @Html.HiddenFor(m => m[i].Id) @Html.HiddenFor(m => m[i].Code) @Html.HiddenFor(m => m[i].Name) <!-- 其他需要提交的字段同理添加HiddenFor --> </td> <td>@Html.DisplayFor(m => m[i].Id)</td> <td>@Html.DisplayFor(m => m[i].Code)</td> <td>@Html.DisplayFor(m => m[i].Name)</td> <!-- 其他展示字段保持不变 --> </tr> } } <input type="button" id="deleteItems" value="Delete Selected Items" class="btn btn-primary btn-large" /> } </tbody>
3. 修正AJAX提交代码
@section scripts{ <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> <script> $(document).on("click", "#deleteItems", function () { var materials = []; // 只遍历选中复选框的行 $(".checkbox:checked").closest("tr").each(function () { var row = $(this); var material = { isSelected: true, Id: row.find("td:eq(1)").text().trim(), Code: row.find("td:eq(2)").text().trim(), Name: row.find("td:eq(3)").text().trim(), Description: row.find("td:eq(4)").text().trim(), BatchNumber: row.find("td:eq(5)").text().trim(), RfId: row.find("td:eq(6)").text().trim(), Weight: row.find("td:eq(7)").text().trim(), MaterialDrawerNo: row.find("td:eq(8)").text().trim(), MaterialLocation_X: row.find("td:eq(9)").text().trim(), MaterialLocation_Y: row.find("td:eq(10)").text().trim(), RemainingTime: row.find("td:eq(11)").text().trim(), PickUpTime: row.find("td:eq(12)").text().trim(), OutsideTime: row.find("td:eq(13)").text().trim(), CabinStatus: row.find("td:eq(14)").text().trim(), TimeAlarm: row.find("td:eq(15)").text().trim(), LifeEnding: row.find("td:eq(16)").text().trim(), TimeProcess: row.find("td:eq(17)").text().trim() }; materials.push(material); }); $.ajax({ type: "POST", url: "/LastedStatus/StartProcedure", data: JSON.stringify(materials), contentType: "application/json; charset=utf-8", dataType: "json", success: function (r) { alert(`成功删除 ${r.count} 条记录`); // 删除页面上选中的行 $(".checkbox:checked").closest("tr").remove(); }, error: function (xhr) { alert("提交失败:" + xhr.responseText); } }); }); </script> }
内容的提问来源于stack exchange,提问作者MMK
相关产品推荐
相关产品推荐

