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

.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>
}

问题原因及解决方案

核心问题分析

  1. Model绑定命名错误:foreach循环生成的input标签没有带索引的命名(如[0].isSelected),MVC无法识别为列表格式,导致参数绑定失败。
  2. AJAX提交逻辑错误:
    • 未筛选选中的行,而是遍历所有行;
    • 获取复选框状态用html()错误,应使用prop("checked")获取布尔值;
    • 部分字段索引错误(如第一种AJAX中RemainingTime重复使用了eq(0));
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 21:08:11