假设我在IIS(虚拟版本7)中有一个名为Foo的虚拟目录.因为我的Default.aspx作为主页. Global.asax示例文件如下:
<%@ Application Language="C#" %> <script runat="server"> void Application_AcquireRequestState(object sender,EventArgs e) { HttpContext.Current.Session["key"] = "value"; } </script>
当我在浏览器中访问http://localhost/Foo/Default.aspx时,工作正常.当我访问http:// localhost / Foo /我得到一个NullReferenceException,我在会话中设置值.唯一的变化是浏览器中的URL.它们最终会击中同一页面,但是框架的行为方式与URL是否仅包含文件夹名称有关,还是包含aspx文件.
检查是否(HttpContext.Current.Session!= null)对我来说不是一个选项,因为我需要在会话中为每个请求设置一个值,这是不可协商的.
在IIS中有一个配置设置,我错过了,还是这个bug /被遗忘的功能?
another question的答案暗示了IIS不会为每种请求加载会话,例如样式表不需要会话.也许这种行为是发生的,因为IIS无法提前告知该文件夹名称是否会导致执行一个aspx文件,或者是否会传递静态HTML文件?
更新:我甚至尝试重新排序IIS查找的默认文档,以便“default.aspx”在列表的顶部,例如
> default.aspx
> Default.asp
> Default.htm
> …
而且我仍然遇到同样的问题.
更新:
事件处理程序只会被触发一次,因为它导致了一个NullReferenceException.我已经做了一些额外的阅读,我知道ASP.NET为每个请求触发这些事件,即使是CSS或JavaScript文件.另外,会话对象没有为静态文件加载,因为没有访问会话的代码,因此不需要加载该对象.即使如此,第一个请求是对网页的请求,这将需要会话,会话为空.
@DmytroShevchenko问:
First add a guard check
if (HttpContext.Current.Session != null)
so that there is noNullReferenceException
thrown. Then try to see,maybe the event will be fired a second time,with a session available.
void Application_AcquireRequestState(object sender,EventArgs e) { if (HttpContext.Current.Session != null) { HttpContext.Current.Session["key"] = "value"; } }
我在if语句中设置了一个断点.我看到这个事件发生4次:
> session为null
> session为null
> session not null
> session为null
当继续每次执行代码时,只有当它开始执行Default.aspx及其代码隐藏时,我有一个会话可用.我实际上在Firefox中打开了网页,并正在监控网络请求.第一个请求是针对http:// localhost / Foo /.
接下来我在Application_BeginRequest中设置一个断点,并得到以下事件:
> BeginRequest
> AcquireRequestState
> BeginRequest
> AcquireRequestState
> BeginRequest
> AcquireRequestState(会话不为空)
>执行Default.aspx(/ Foo返回对浏览器的响应)
> BeginRequest
> AcquireRequestState(会话再次为null)
在#9,浏览器中的AJAX请求到http:// localhost:54859 / 8fad4e71e57a4caebe1c6ed7af6f583a / arterySignalR / poll?transport = longPolling& connectionToken = …& messageId = …& requestUrl = http:// localhost / Foo /& browserName = Firefox& userAgent = Mozilla / 5.0(Windows NT 6.1; WOW64; rv:41.0)Gecko / 20100101 Firefox / 41.0& tid = 4& _ = 1445346977956正在等待响应.
解决方法
使用MVC和WebAPI,引入了一个新的HttpModule:ExtensionlessUrlHandler.我相信您的事件多次发射(只有一次会话可用)可能是由该模块或ASP.NET的其他(重新)路由逻辑引起的,该逻辑实际上重定向ASP.NET来处理Default.aspx.
另外,正如你自己提到的,这些事件可以被触发为静态文件请求.
最重要的是,每当你的事件触发时,你不应该依靠会话.但是,假设您可以在提供ASP.NET页面时至少访问一次会话是安全的.因此,这是你的代码应该如下所示:
void Application_AcquireRequestState(object sender,EventArgs e) { if (HttpContext.Current.Session != null) { HttpContext.Current.Session["key"] = "value"; } }