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

.NET MVC 分部视图表格每行DropDownListFor提交状态异常问题求助

问题分析与解决方案

这个问题的核心原因有两个,咱们一步步拆解:

  1. 重复的表单控件名称:你用foreach循环生成每行的HiddenFor和DropDownListFor时,所有控件都会绑定到ViewModel的同一个属性(idSelected和SelectedEstadoRow),导致HTML里所有下拉框的name都是SelectedEstadoRow,所有隐藏域的name都是idSelected。浏览器提交表单时,只会发送这些重复名称中的某一个值(通常是第一个或最后一个),所以控制器永远拿不到你点击修改那一行的对应数据。

  2. 请求方式不匹配:你用Html.ActionLink生成的是<a>标签,默认发起GET请求,但你的控制器方法是接收POST请求的,这本身就不符合规范,甚至可能导致数据提交失败。


最简单的修复方案:每行单独一个表单

既然是单行修改,给每行单独创建一个表单是最直接的方式,这样每个表单只会提交当前行的id和选中的状态:

<table id="table" class="table">
    <tr>
        <th>Id</th>
        <th>Descrição</th>
        <th>Início</th>
        <th>Fim</th>
        <th>Origem</th>
        <th>Estado</th>
        <th></th>
        <th></th>
    </tr>
    @if (Model.listGestaoAfericoes != null) {
        foreach (var item in Model.listGestaoAfericoes) {
            // 把表单放到每行内部
            using (Html.BeginForm("AlterarEstadoAfericao", "Ferramentas", FormMethod.Post)) {
            <tr id="@item.id">
                <td>@item.id</td>
                <td>@item.descricao</td>
                <td>@item.data_ini_afericao</td>
                <td>@item.data_fim_afericao</td>
                <td>@item.origem_afericao</td>
                <td>@item.id_estado_actual</td>
                <!-- 直接指定隐藏域的名称和值,避免重复绑定 -->
                @Html.Hidden("idSelected", item.id)
                <td>Estado: @Html.DropDownList("SelectedEstadoRow", (IEnumerable<SelectListItem>)Model.listEstados)</td>
                <td>
                    <!-- 用submit按钮代替ActionLink,确保发起POST请求 -->
                    <button type="submit" class="btn btn-info" onclick="return confirm('Tem a certeza que pretende alterar o estado?');">
                        Alterar Estado
                    </button>
                </td>
            </tr>
            }
        }
    }
</table>

控制器代码优化(可选)

你可以直接用参数接收需要的值,不用传递整个ViewModel,代码会更简洁:

public ActionResult AlterarEstadoAfericao(int idSelected, string SelectedEstadoRow) {
    GestaoAfericoesDbo gestaoAfericoesDbo = new GestaoAfericoesDbo();
    DbUtil dbUtil = new DbUtil();
    string connectionString = dbUtil.generateConnectionString(Connections.Endpoint);
    
    using (var db = new IntranetDbContext(connectionString))
    {
        try {
            var idEstado = db.AF_Estado.First(a => a.descricao.Equals(SelectedEstadoRow));
            int id_estado = Convert.ToInt32(idEstado.id);
            
            var dbAF_afericao = db.AF_afericao.Find(idSelected);
            dbAF_afericao.id_estado_actual = id_estado;
            db.SaveChanges();
        } catch(SqlException exc) {
            Console.WriteLine(exc);
        }
    }
    return RedirectToAction("GestaoAfericoes");
}

这里做了两个小优化:

  • 用First()代替ToList().First(),减少不必要的内存开销
  • 把DbContext放到using块里,确保自动释放资源

这样修改后,每行的表单只会提交自己的idSelected和SelectedEstadoRow值,控制器就能正确拿到你修改的那一行的状态了。

内容的提问来源于stack exchange,提问作者Nuno Santos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 10:04:07