我在使用HiddenFor和Hidden助手来存储要发布回Controller的数据时遇到问题。我有一个控制器有两种方法:
Function Index() As ActionResult
Dim model As New FormPOSTViewModel With {.Name = "Test", .Description = "Test description goes here", .Value = 12}
Return View(model)
End Function
<HttpPost>
Function Update(model As FormPOSTViewModel) As ActionResult
Dim updated As New FormPOSTViewModel
updated.Name = model.Name & "_x"
updated.Description = model.Description & "_x"
updated.Value = model.Value * 2
Return View("Index", updated)
End Function
和一个包含三种形式的视图,一种使用HTML,一种使用HiddenFor,另一种使用Hidden:
@ModelType MVCAjaxWorkbench.FormPOSTViewModel
@Using Html.BeginForm("Update", "FormPOST")
@:<table>
@:<tr><td>@Html.DisplayFor(Function(m) Model.Name)</td></tr>
@:<tr><td><input type="hidden" id="Name" name="Name" value="@Model.Name" /></td></tr>
@:<tr><td><input type="hidden" id="Description" name="Description" value="@Model.Description" /></td></tr>
@:<tr><td><input type="hidden" id="Value" name="Value" value="@Model.Value" /></td></tr>
@:</table>
@:<input type="submit" />
End Using
@Using Html.BeginForm("Update", "FormPOST")
@:<table>
@:<tr><td>@Html.DisplayFor(Function(m) Model.Name)</td></tr>
@:<tr><td>@Html.Hidden("Name", Model.Name)</td></tr>
@:<tr><td>@Html.Hidden("Description", Model.Description)</td></tr>
@:<tr><td>@Html.Hidden("Value", Model.Value)</td></tr>
@:</table>
@:<input type="submit" />
End Using
@Using Html.BeginForm("Update", "FormPOST")
@:<table>
@:<tr><td>@Html.DisplayFor(Function(m) Model.Name)</td></tr>
@:<tr><td>@Html.HiddenFor(Function(m) Model.Name)</td></tr>
@:<tr><td>@Html.HiddenFor(Function(m) Model.Description)</td></tr>
@:<tr><td>@Html.HiddenFor(Function(m) Model.Value)</td></tr>
@:</table>
@:<input type="submit" />
End Using
和ViewModel:
Public Class FormPOSTViewModel
Public Property Name As String
Public Property Description As String
Public Property Value As Integer
End Class
我想要发生的是,每次按下提交按钮时,模型都会更新,多次将'_x'附加到结尾,以便它最终结束'Test_x_x_x_x_x_x'。如果我在手工创建HTML的表单中使用“提交”按钮,那么一切正常。
然而,当我解锁并按下其中一个其他提交按钮时实际发生的事情是,只会附加一个'_x'。这似乎是因为Update方法在第二次及以后的时间接收的模型是原始Index方法发送到页面的模型。
这是Hidden / HiddenFor的错误还是我错误地使用它们?
答案 0 :(得分:3)
不,这不是一个错误。回发模型后,属性的值将添加到ModelState
。返回视图时,ModelState
中的值优先于您可能尝试在控制器中覆盖的任何值。您首先需要使用
ModelState
值
ModelState.Clear();
现在,当您设置属性的值时,Html帮助程序将使用属性值。
答案 1 :(得分:1)
来自Simon Ince's Blog,其中包含问题说明以及为何需要使用ModelState.Clear调用:
ASP.NET MVC假设您在渲染视图以响应 HTTP POST,你正在使用Html助手,那么你很有可能 重新显示验证失败的表单。因此, Html Helpers实际上在ModelState中检查要显示的值 在他们查看模型之前的字段。这使他们能够重新显示 用户输入的错误数据和匹配错误 消息,如果需要。
由于我们的[HttpPost] Index重载依赖于Model Binding 解析POST数据后,ModelState已自动填充 字段的值。在我们的操作中,我们更改了模型数据(不是 ModelState),但是Html助手(即Html.Hidden和 Html.TextBox)首先检查ModelState ...然后显示值 被行动收到,而不是我们修改的那些。
因此,要解决此问题,我们必须在Controller的Update方法中添加一行:
Function Update(model As FormPOSTViewModel) As ActionResult Dim updated As New FormPOSTViewModel updated.Name = model.Name & "_x" updated.Description = model.Description & "_x" updated.Value = model.Value * 2 ModelState.Clear() Return View("Index", updated) End Function