ASP.NET MVC - 跨视图传递数据

8
我正在构建一个MVC应用程序。我的任务之一是构建一个商店。我设置了一组“向导”样式的视图,将用户带到填写不同类型数据的不同步骤,共7个步骤。
我的问题是如何在所有这些视图之间共享某些数据。
首先,我使用了老式的Session,在我的桌面上一切正常,但当我最终将应用程序部署到公司的托管服务器上时,我收到了异常,因为Session在某些步骤中会被随机清除。
现在,我修改了所有内容,将我需要的任何数据都设置在TempData中,并在每个步骤中刷新所有数据,它似乎可以正常工作。
我有点困惑!
我的困惑在于所有这些结构:Session(我知道它来自asp.net),ViewData,TempData和神奇的ViewBag。
我读了很多关于它们的文章,但我需要有人清楚地告诉我在这种情况下什么更适合我。

1
Steven Sanderson在他的书《Pro ASP.NET MVC 2》的第13章“Wizards and Multistep Forms”中详细讨论了这个主题。如果你有这本书,可以去查看一下。 - archil
我买了这本书,现在正在等待亚马逊先生!与此同时,我的老板问我为什么我们的网站不能正常工作!这是一种艰难的生活! - JasonMenny
实际上,TempData 的默认后备存储是 Session。因此,当会话经常被清除时,我不会期望它能正常工作。不过要小心。 - archil
我知道,事实上我正在将值放入TempData中,将该值放入某些HiddenField中,然后在我的[HttpPost]操作中重新将其放回TempData。不太优雅,但是有效。 - JasonMenny
1
这个答案可能会对你有所帮助:https://dev59.com/ZGw15IYBdhLWcg3wxurL#6403485 - archil
3个回答

3
我认为ViewBag非常适合这种情况。现在,你把ViewBag称为“Magic” viewbag,但实际上它只是包装了一个字典的ViewData,该字典的键值对类型是<string,object>
ViewBag的工作方式是它只是ViewData周围的一个动态包装器,所以当你请求某些东西时,比如ViewBag.ShoppingCart,它基本上会询问底层字典是否有一个名为“ShoppingCart”的条目,并返回该项。
更新:问题在于我没有记住ViewBag和ViewData是与视图相关的,因此每当您访问不同的视图/操作时,它们都会被清空。
除非您需要将ShoppingCart(或向导进度)存储在数据库中,否则在您的情况下,我会选择TempData而不是ViewBag :)
您还可以查看Rachel Apple的这篇文章,以获取更多关于这三个的信息:

http://rachelappel.com/when-to-use-viewbag-viewdata-or-tempdata-in-asp.net-mvc-3-applications

(附注:我建议阅读该帖子的评论,以获得更多不偏见的意见)


1
在这种情况下,ViewBag 如何使用?我理解问题是,他需要客户端多步骤向导,并且他想保存每个步骤的数据以便下一步使用。 - archil
事实上,如果我理解了 ViewBag(和 ViewData),它不是我所需的。我需要一个结构,在移动到我的视图时可以放置一些值。现在我在每个视图中都使用 TempData 和 HiddenField,这不太优雅,但现在它正在发挥作用。 - JasonMenny
JasonMenny:对不起,我犯了一个错误,因为ViewBag(ViewData)是特定于操作的。TempData则不是,那么为什么不使用它呢?@archil他指定“在视图之间”,所以我没有将其解读为客户端,而是实际调用不同的ActionMethods。我会更新我的答案。 - Yngve B-Nilsen

2
“使用隐藏字段没有问题——至少在我的书中是这样的。我会‘修复’Session问题,而不是试图在问题周围编写代码。运行一个简单的测试:将Session提供程序更改为SQL,禁用隐藏字段,然后查看您的应用程序是否正常工作。如果它不能正常工作,则必须担心其他(更大的)问题。”
“这个应用程序是否应该在Web农场/‘云’/负载均衡器后面工作?如果是这样,你需要:”
“1. 将会话提供程序更改为其他东西:SQL、StateServer、内存缓存等。不需要太多代码更改。”
http://msdn.microsoft.com/en-us/library/ms178587.aspxhttp://memcachedproviders.codeplex.com/
“或者”
“2. 重新设计向导步骤,并减少视图之间共享值的依赖性。只需Session ID即可,您可以查询数据库获取其他内容。速度不快,但安全稳定。”
优化:可以使用尽可能多的隐藏字段来减少数据库查询次数(像我之前说的,这没有问题),但通常一个字段就足够在请求之间保持序列化状态了:http://blog.maartenballiauw.be/post/2009/10/08/Leveraging-ASPNET-MVC-2-futures-ViewState.aspx
即使您不必担心应用程序的多个实例(在不同的计算机上),IIS也会定期回收工作进程。当它这样做时,您可能会在同一台机器上同时运行两个实例(短时间内),并且您的一些用户可能恰好在这些时刻命中服务器。
下一个请求是否命中应用程序的不同实例并不重要。始终尝试以此目标为设计目标。
希望对你有所帮助!

0
你有几个选择: 使用会话、视图数据(或视图包),但需要使用隐藏字段或 cookie 传递它。
视图数据的问题是会增加更多的工作量。
我会选择会话,但也许在你的情况下会被清除,因为你可能有多台服务器,当第二个请求到达另一台服务器时,它就没有来自上一个步骤的数据了。
解决这个问题可以使用一个为所有服务器保存会话的服务器,或者使用 cookie(如果信息不是关键的话)。

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