2010-07-29 72 views
8

我们有一个MVC.NET应用程序,它在重新启动时遇到致命错误。在我们的Session_Start事件处理程序中,我们将会话ID添加到字典中。在Session_End处理程序中,我们将其删除。考虑请求的顺序如下:ASP.NET MVC应用程序为单个会话多次触发Session_Start

GET home.mvc
<应用程序重新启动>
GET的main.css
GET banner.jpg
GET somedata.mvc
...

由于应用程序的架构方式,如果在浏览器窗口中打开应用程序时执行重建,则这种顺序发生的频率相当高。除非我在生产环境中看到它,否则这不会非常令人担忧。例如,编辑web.config时会发生(尽管很少)。

重新启动后的请求全部归因于主页中的链接或来自JavaScript的AJAX调用。

我观察到.NET并行处理前5个请求。每个这样的请求都会导致它触发Session_Start事件。短时间后,它会触发Session_End事件3次。要清楚,每个Session_Start对应于完全相同的会话。它们都具有相同的会话ID,IsNewSession属性对于所有会话状态对象都是true。另外,Session_End事件而不是对应的会话正在被终止。会话持续存在,以及存储在会话状态中的任何数据。

我需要阻止它多次触发Session_Start,或者想出如何判断Session_End何时并不意味着会话已经结束。

+0

你需要处理什么?你是说你的字典和asp.net的内部字典有差异吗?你在什么时候发现这种差异? – 2010-07-30 17:41:56

+0

字典是存储在应用程序变量还是会话变量中? – 2010-07-30 19:38:02

+0

字典是一个应用程序变量。 – 2010-07-30 20:24:46

回答

3

回答这个问题竟然是相当直盼着,虽然这种行为当然令人困惑。

通常情况下,MVC会将所有请求同步到应用程序的会话状态锁定(因为MVC的http模块被标记为需要会话状态)。在我的场景中,应用程序在服务主页面后重新启动。因此,当主页面相关请求进入时,该会话标识还没有会话状态,并且这些请求并行执行。

我看到5个并行请求,因为我在XP上开发,桌面版本的IIS仅限于5个并发请求。由于这些请求中的任何一个都不存在会话状态对象,因此每个请求都会创建一个新的会话状态对象并触发Session_Start。四个请求转到MVC操作方法。由于这些需要会话状态,一旦请求完成,.NET会尝试将创建的会话状态对象与后备存储同步。

只有第一次同步可以成功。 .NET简单地丢弃三个额外的会话状态对象并为每个对象触发Session_End。 。NET不会尝试将第五个会话状态对象与后备存储同步,因为它是为标记为需要只读会话状态的异步http模块创建的。

因此,修补程序有两个部分:

(1)我在session_start处理程序,我现在检查会话状态对象是只读的。如果是这样,那么我立即返回而不做任何事情。 .NET不会触发相应的Session_End,因此我所做的任何事情都无法正确清理。

(2)我现在在我的字典中保留一个引用计数。每当Session_Start处理程序试图添加一个会话ID并在每次Session_End尝试删除它时递减它,我都会增加计数。一旦计数达到0,我从我的字典中删除会话ID。

+0

它有点老..但我不追随为什么5个请求是并行的。这是从一个请求中产生的吗?为什么同时创建5个? – 2011-06-07 14:08:27

+0

多个请求同时创建,因为浏览器发送多个请求而无需等待它们返回。 (接收到网页后,浏览器立即请求所有引用的图像,样式表等)。因为机器是Windows XP盒子,所以出现了数字5。 IIS限制应用程序在台式机上同时处理5个请求。在服务器盒上,数字会更高。 – 2011-06-09 15:15:28

1

如果客户端向您发送已过期的值,则可以重新使用会话标识。阅读关于<的sessionState >元素的regenerateExpiredSessionId属性here并注意默认值是“真”

您也可能会发现this有趣:

+0

谢谢你的回复马特,但我相信我一直在吠叫错误的树。我会用昨天发现的一些额外信息更新我的问题。 – 2010-07-30 13:51:48

0

我在开发中遇到过一个旧的ASP.NET应用程序时,发生了这种情况 - 事实上,RequireSSL被设置为True以表示cookie ......这当然意味着会话cookie不会被保留/重新发布客户端(本地主机,非SSL) - 所以后续请求创建了新的会话。

相关问题