我还是相对较新的ASP.NET MVC 3,对于那些在这里有更多经验的人,我有一个概念性的问题。
让我们说(简单)示例我有一个事件的注册表单。表单将显示事件的名称,以及用户可以输入其名称的文本框。 ViewModel看起来像这样:
public class SignupFormViewModel {
public string EventName { get; set; }
[Required]
public string VolunteerName { get; set; }
}
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>
}
如果用户将表单提交回服务器并且ModelState无效,我们将返回原始View并传回Model,以便我们显示错误。 (我们假设这个例子是在客户端上没有处理的错误)
问题在于,在我上面显示的示例视图中,EventName未随表单数据一起提交。我只想将它用于页面内容,而不是表单字段。但是如果我必须返回并向用户显示验证错误,我就丢失了EventName属性。
那么我通过回到同一视图的帖子保留这个非表单字段项目的选项是什么?
我知道我可以创建一个隐藏字段来保存EventName属性,但是有一些东西对于被强制将每个非表单字段属性放入隐藏字段时没有异味。我也知道我可以在我的控制器中进入HttpPost动作,然后在返回视图之前将数据重新加载到模型中,但这也很笨拙。
我想我对这方面的基本方法有很好的理解,但我想知道是否有更好的方式或最佳实践感觉更干净......或者我是否只需要学会处理它: - )
由于
答案 0 :(得分:6)
使用隐藏字段没有任何问题。当您实际上不希望它们显示为表单字段时,这是一种将事物保持在请求上的常规方法。
请记住 HTTP是无状态的,所以在POST请求中丢弃某些内容并在POST请求中再次提取它实际上是一种更为一致的方式来保持数据超过多个请求而不是使用另一种机制,给出了有状态的幻觉。
如果您认为这会使您的标记过于混乱,您可以尝试将值放入初始GET请求的TempData
集合中,该集合仅在下一个请求期间存在,允许您在你的下一个控制器动作中选择它:
TempData["MyVar"] = model.EventName
但是,如果您希望将此功能保留在您的模型中,就像传统(以及 - 我认为 - 最佳)方式一样,隐藏字段仍然是可行的方法:
@Html.HiddenFor(m => m.EventName)
为了进一步阅读,您可能还会考虑cookies或session state,但这些都不会保留模型中的值。然而,这两种机制都有其局限性,我在another answer, here.
中概述了这些局限