Html.HiddenFor和Html.Hidden没有正确地回到控制器

时间:2014-12-03 09:25:44

标签: razor asp.net-mvc-5 html-helper

我在使用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的错误还是我错误地使用它们?

2 个答案:

答案 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
相关问题