.NET MVC 分部视图表格每行DropDownListFor提交状态异常问题求助
问题分析与解决方案
这个问题的核心原因有两个,咱们一步步拆解:
重复的表单控件名称:你用
foreach循环生成每行的HiddenFor和DropDownListFor时,所有控件都会绑定到ViewModel的同一个属性(idSelected和SelectedEstadoRow),导致HTML里所有下拉框的name都是SelectedEstadoRow,所有隐藏域的name都是idSelected。浏览器提交表单时,只会发送这些重复名称中的某一个值(通常是第一个或最后一个),所以控制器永远拿不到你点击修改那一行的对应数据。请求方式不匹配:你用
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
相关产品推荐
相关产品推荐

