在ASP.NET MVC中保留非表单模型数据

Ben*_*ndt 6 asp.net-mvc asp.net-mvc-3

我还是相对较新的ASP.NET MVC 3,对于那些在这里有更多经验的人,我有一个概念性的问题.

让我们说(简单)示例我有一个事件的注册表单.表单将显示事件的名称,以及用户可以输入其名称的文本框.ViewModel看起来像这样:

public class SignupFormViewModel {
   public string EventName { get; set; }
   [Required]
   public string VolunteerName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Razor视图可能如下所示:

<h2>Sign up for @Model.EventName</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<div class="editor-field">
    @Html.EditorFor( model => model.VolunteerName )
    @Html.ValidationMessageFor( model => model.VolunteerName  )
</div>
}
Run Code Online (Sandbox Code Playgroud)

如果用户将表单提交回服务器并且ModelState无效,我们将返回原始View并传回Model,以便我们显示错误.(我们假设这个例子是在客户端上没有处理的错误)

麻烦的是,在我上面显示的示例视图中,EventName未随表单数据一起提交.我只想将它用于页面内容,而不是表单字段.但是如果我必须返回并向用户显示验证错误,我就丢失了EventName属性.

那么我通过一个回到相同视图的帖子保留这个非表单字段项目的选项是什么?

我知道我可以创建一个隐藏字段来保存EventName属性,但是有一些东西对于被强制将每个非表单字段属性放入隐藏字段时没有异味.我也知道我可以在我的控制器中进入HttpPost动作,并在返回视图之前将该数据重新加载到模型中,但这也感觉很笨拙.

我想我对这方面的基本方法有很好的理解,但我想知道是否有更好的方法或最佳实践感觉更干净......或者如果我只是要学会处理它:-)

谢谢

Ant*_*t P 7

使用隐藏字段没有任何问题.当您实际上不希望它们显示为表单字段时,这是一种将请求持久化的常规方法.

请记住,HTTP是无状态的,因此在POST请求中删除某些内容并在POST请求中再次提取它实际上是一种更为一致的方法,即将数据保留在多个请求上,而不是使用另一种机制来提供有状态的假象.

如果您认为这会使您的标记过于混乱,您可以尝试将值放入TempData初始GET请求的集合中,该请求仅在下一个请求的持续时间内存在,允许您在下一个控制器操作中将其拾取:

TempData["MyVar"] = model.EventName
Run Code Online (Sandbox Code Playgroud)

但是,如果您希望将这个保留在模型中,就像传统(以及 - 在我看来 - 最好)这样做的方式,隐藏字段仍然是要走的路:

@Html.HiddenFor(m => m.EventName)
Run Code Online (Sandbox Code Playgroud)

为了进一步阅读,您可能还会考虑cookie会话状态,但这些都不会保留模型中的值.然而,这两种机制都有其局限性,我在另一个答案中概述了这一点.