ASP.NET MVC - TempData - 是好还是坏的实践?

97

我正在使用Scott Gu的第5版预览博客中详细介绍的AcceptVerbs方法来处理ASP.NET MVC中的表单条目:

  • 用户通过GET获取空表单
  • 用户将填好的表单通过POST提交到同一操作中
  • 操作验证数据,执行适当的操作,然后重定向到新视图

因此,我不必使用TempData。 话虽如此,现在我需要在这个过程中添加一个“确认”步骤,似乎需要使用TempData

由于某种原因,我有些抵制使用TempData - 觉得可以设计得更好。

这是否是一个有效的顾虑,还是我在瞎担心?


1
考虑将您的“确认”步骤设置为JavaScript对话框。这样可以减少服务器往返次数,也不会遇到这个问题。 - ajma
8个回答

79

没有必要对TempData有所抵触...但是,如果使用不当,它确实可能是设计不良的标志。如果您正在使用RESTful URL,则TempData是将消息从POST操作传输到GET操作的最佳实践。考虑以下情况:

您在URL Products/New上有一个表单。该表单发布到Products/Create,该操作验证表单并创建产品。成功后,控制器重定向到URL Products/1;如果出现错误,则重定向回products/New以显示错误消息。

Products/1只是产品的标准GET操作,但我们希望显示一个消息,指示插入成功。这时TempData非常适合。在Post Controller中添加消息到TempData,然后在视图中添加一些if逻辑,就完成了。

失败时,我会在Post操作中向TempData添加表单集合中输入的值和错误消息的集合,并重定向到初始操作Prodcuts/New。我已经在视图中添加了逻辑,以填充表单输入与先前输入的值以及任何错误消息。我认为这很简洁明了!


1
为什么要做额外的工作,如果你可以直接发布到Products/New呢?Products/Create有什么价值? - mpen
2
@Mark,使用Products/Create可以避免用户在postback完成操作后,在稍后的刷新(或书签和返回)中意外重新完成操作的情况。更多信息请参见http://en.wikipedia.org/wiki/Post/Redirect/Get。 - ehdv
3
@ehdv说:“但是它真的会这样吗?成功后会重定向到另一个页面,在失败时应显示表单错误,不应采取任何行动,因此没有任何损害。它只会防止令人讨厌的“您确定要重新发布吗?”消息,而我经常想要这样做。不过我想这取决于你的设计,所以我能理解你的观点。” - mpen

31

我认为在使用TempData之前,你最好先犹豫一下。 TempData存储在会话中,如果:

  1. 您的网站现在不使用会话
  2. 您拥有一个需要扩展到高吞吐量的系统,即您更倾向于完全避免会话状态
  3. 您不想使用cookie(我不知道MVC目前对无cookie会话的支持情况)

如果您的网站需要具有高可用性,则还需要考虑会话状态的其他问题,但这些都是可以解决的问题。


16
TempData不一定要存储在会话中,尽管它是默认提供程序,这也可能是为什么它不在方法文档中的原因。还有一个cookie提供程序,作为编写自定义提供程序的示例。 - FinnNk

26

我认为暂存数据有点像一种提示用户的即时性机制,这样可以很好地提醒他们最近所做的事情,但是我也不太愿意将其作为某些用户流程中必需的步骤。原因是如果用户刷新页面,我相信数据会丢失。另外,它的可靠性并没有被很好地定义,所以我也有些犹豫使用它。

我想知道问题是否出在您将操作重定向到其他页面之前进行确认步骤上。我想知道是否可以在首次提交后进行足够的处理来生成确认对话框,然后返回原始页面以显示确认问题。类似于如何进行验证,但验证规则检查确认步骤是否已执行(确认 UI 在其他验证通过之前隐藏)。


3

查看MVC3中的无会话控制器。结果表明,使用会话会阻止单个用户请求的并行执行,从而导致性能下降。

由于tempdata默认使用会话,因此您将无法使用此功能。您可以切换到使用cookie进行tempdata,但这有点尴尬(至少对我来说是这样)。尽管如此,比viewstate更清晰,所以也许这不是一个很大的障碍。


2
关于无会话控制器和TempData使用会话,您是正确的。但是等等! 会话并不是坏事,您可以混合和匹配无会话和会话控制器。当您从浏览器向服务器发出大量AJAX调用时,您确实希望使用Session_less_控制器。当您只点击一个页面时,您不需要无会话。实际上,这不应该给您任何好处...因为您只向服务器发送一次请求。因此,可以混合和匹配。 - Pure.Krome

3

我有一个GetModel方法,首先检查TempData ["model"]是否存在,如果存在则返回该值。否则,GetModel从数据库中加载相应的数据。

当我需要返回需要相同模型数据的不同视图的操作时,它可以避免额外的数据库负载。


是的,我遇到了这个问题:(1)验证记录是否存在,如果有效,则重定向到页面(2)加载记录以供用户显示。因此,数据库会进行验证和显示。我几乎要使用TempData来解决这个问题,但感觉需要听听意见。不过我喜欢你的方法来处理它。 - anonymous
1
在这种情况下,最好使用适当的缓存机制。 - nicodemus13

2
这就像使用ViewData,意味着它可能不会存在安全风险。但我更愿意使用ViewData而不是TempData。点击此处进行比较:http://www.squaredroot.com/2007/12/20/mvc-viewdata-vs-tempdata/ 根据设计,您可以始终将用户/购物篮或任何需要的内容存储在数据库中的tempdata中,并只需具有“IsReady”字段,该字段指示是否已完成,使其可扩展以供以后考虑,人们可以关闭他们的浏览器。

2
注意:您链接的文章是当时最新的,但仅适用于MVC1。TempData在MVC2中发生了相当大的变化。 - mikemanne
@mikemanne,是的。但是答案是来自2008年末的。也许应该更新一下答案? - Filip Ekberg

2

为什么你有这样的厌恶?这个东西只是在完成它的工作,并且做得很好 :)

如果你不喜欢它因为它不是强类型的,你可以随时创建一个包装器来提供强类型接口。


0
所有良好的答案,您看过这个传递消息的示例了吗。
TempData和Session不是RESTful架构的最佳选择,因为大多数会话存储在内存中。因此,当您想要使用服务器群集时,用户会话将存在于一个服务器上,而他们的下一个请求可能会被发送到另一个服务器。
话虽如此,请查看此处使用TempData传递消息的示例。

http://jameschambers.com/2014/06/day-14-bootstrap-alerts-and-mvc-framework-tempdata/

也许,如果仅用于重定向到另一页的警报,则可以改用查询字符串方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接