为什么ASP.NET MVC会使用会话状态?

33

推荐使用缓存而不是会话,ASP.NET团队建议我们在过去的几年里停止使用会话来处理WebForm模型。因此,我们通常会在web.config中关闭会话。

<sessionState mode="Off" />

但是,现在我正在测试一个使用此设置的ASP.NET MVC应用程序,它在mvc框架内的SessionStateTempDataProvider类中抛出错误,要求我打开会话状态,我这样做了,并且它可以工作。查看源代码,它使用会话:

// line 20 in SessionStateTempDataProvider.cs
Dictionary<string, object> tempDataDictionary = 
httpContext.Session[TempDataSessionStateKey] as Dictionary<string, object>; 

那么,为什么他们在这里使用session?我漏掉了什么吗?

========================================================

编辑 很抱歉本帖并不是要辩论session与cache的优劣,而是在ASP.NET MVC的上下文中,我想知道为什么这里要使用session。Scott Watermasysk在这篇博客文章中也提到,关闭session是一个好习惯,所以我想知道为什么我必须开启它才能从这里开始使用MVC。


你能提供一个链接,证明他们说“使用缓存而不是会话”,因为它们实际上并不是用于同一目的吗? - Filip Ekberg
如果我没记错的话,我是在 MSDN 杂志的 2005 年 9 月份读到的。也许我应该用更好的措辞,但我们根本不使用 session。 - Ray
他说:“提示:不使用时禁用会话状态。” 在经过身份验证的区域中很少不使用会话。 - Filip Ekberg
提供的 Scott 链接已经失效。 - Shane Courtrille
顺便提一下,关于会话状态的文章可以在MSDN杂志2005年9月号中阅读此处 -- 请注意,它是指ASP.NET 2.0的预发布版本。 - edymtt
4个回答

33

Session被用于TempData存储。TempData是一种高度受限的会话状态,它仅持续到来自某个特定用户的下一个请求。(MVC 2+中,它会持续到下次读取。) TempData的目的是存储数据,然后重定向,在刚刚重定向的操作中使用存储的数据。

使用Session作为TempData存储意味着任何已处理Session的分布式缓存系统都可以处理TempData。避免直接使用Session而不是TempData有几个优点之一是您不必自己清理Session;TempData会自动“过期”。


3
在轮询的 Web Farm 配置中,这个功能是如何工作的?在 MVC 中有没有关闭 Session State/TempData 的方法? - Chuck Conway
2
它的工作方式与会话在服务器群上始终工作的方式相同。这在MSDN上有记录。最好的方法是使用分布式缓存,但您也可以使用“粘性会话”。关于关闭会话,同样,它就像任何其他ASP.NET应用程序一样。请参阅MSDN。然后只需不使用TempData即可。尽管如此,这样做就像通过斩首治疗痤疮。 - Craig Stuntz
10
可以通过在web.config中禁用并实现ITempDataProvider接口来禁用会话状态。 - Chuck Conway
@Craig 该死的你。我刚写完一个问题,再次检查是否有重复时发现这里已经有了答案。浪费了大约15分钟... xD - Arnis Lapsa
Santose:在MVC 1中,在下一个请求时。在MVC 2 beta+中,当它被下一次读取时。 - Craig Stuntz
Craig,你可能需要编辑一下你的MVC 2+答案(就像你在上面的评论中所做的那样)。人们会阅读你的答案并跳过这部分。 - RickAndMSFT

13

ASP.NET团队建议使用缓存而非会话

@ray247,你能提供一下参考资料吗?会话和缓存本质上是不同的,应根据应用程序要求来选择使用。例如,将用户特定数据存储到缓存中可能会导致不良行为。当然,如果您确实想避免使用会话,可以提供自己的ITempDataProvider接口实现。


顺便问一句,将用户特定数据存储到缓存中为什么会导致不良行为?如果您针对每个用户正确获取缓存键,我不认为这是一个问题。 - Ray
4
因为缓存的定义本质上是易失性的,所以存在一些情况超出你的掌控范围,比如内存压力,会导致缓存被清空,从而丢失所有会话数据。 - Darin Dimitrov
1
默认情况下,ASP.NET应用程序将会话状态存储在工作进程的内存中,具体来说是在Cache对象的私有插槽中。 - Chris Shouts

6

嗯...也许你已经了解过持久化重对象或相对不常访问的对象-将它们放入缓存中肯定是更好的选择,但对于轻量级对象或每次请求都需要的数据来说,没有比将它们放入Session中更好的技术了。

如果使用正确,Session并不是邪恶的。


1
知道这是一个老问题,但是这个答案(以及其他所有答案)忽略了OP使用的是WebFarm基础架构这一事实,这意味着需要使用SQL Server(对于这项任务来说相当慢)或专用的、网络共享的Windows服务(非常麻烦)来保持会话 - 因此缓存可能确实是更好的选择。 - rsenna

3

只是一个额外的想法。TempData 有其自身的目的,MS 知道在 TempData 持久化机制方面会有不同的思路。因此,默认情况下,他们将持久存储设置为 SessionState。但设计仍然非常灵活。根据项目的需求和指导它的治理,您可以创建自己的 tempdata 提供程序以满足特定要求。

以下是一些资源的指针 TempData

以下是 TempData 实现的一些额外改进 TempData Improvements

这是使用 MS Velocity 分布式缓存的替代实现。 Velocity TempData Provider


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