在浏览器中加载虚拟目录名时,会话在AcquireRequestState中为空,但在加载Default.aspx时不为null
我有一个ASP.NET 4.0 WebForms应用程序。 我需要访问HttpContext.Current.Session
并在Global.asax中的AcquireRequestState
事件(或它后面的事件)中设置一个值,我发现了一种奇特的行为。
假设我在IIS(我的案例中为版本7)中有一个名为Foo
的虚拟目录。 在那里我有Default.aspx
作为主页。 Global.asax
文件示例如下:
void Application_AcquireRequestState(object sender, EventArgs e) { HttpContext.Current.Session["key"] = "value"; }
当我在浏览器中访问https://localhost/Foo/Default.aspx
时,它运行正常。 当我访问https://localhost/Foo/
我得到一个NullReferenceException
,我在会话中设置值。 唯一的变化是浏览器中的URL。 它们最终会访问同一页面,但框架的行为会有所不同,具体取决于URL是否只包含文件夹名称,还是包含aspx文件。
检查if (HttpContext.Current.Session != null)
对我来说不是一个选项,因为我需要在会话中为每个请求设置一个值,这是不可协商的。
IIS中是否存在我缺少的配置设置,或者这是一个错误/被遗忘的function?
另一个问题的答案暗示IIS不会为每种请求加载会话,例如样式表不需要会话。 也许这种情况正在发生,因为IIS无法提前判断该文件夹名称是否会导致执行aspx文件或者是否会提供静态HTML文件?
更新:我甚至尝试重新排序IIS查找的默认文档,以便“default.aspx”位于列表的顶部,例如
- Default.aspx的
- Default.asp的
- Default.htm的
- …
我仍然遇到同样的问题。
更新:
事件处理程序只被触发一次,因为它导致NullReferenceException
。 我已经做了一些额外的阅读,我知道ASP.NET会为每个请求触发这些事件,即使对于CSS或JavaScript文件也是如此。 此外,没有为静态文件加载会话对象,因为没有访问会话的代码,因此无需加载对象。 即便如此,第一个请求是对网页的请求,该请求将需要会话,并且会话为空。
@DmytroShevchenko问:
首先添加一个保护检查
if (HttpContext.Current.Session != null)
,这样就不会抛出NullReferenceException
。 然后尝试看一下,也许这个事件会被第二次发射,并且会话可用。
修改后的代码
void Application_AcquireRequestState(object sender, EventArgs e) { if (HttpContext.Current.Session != null) { HttpContext.Current.Session["key"] = "value"; } }
我在if
语句中设置了一个断点。 我看到这个事件发生了4次:
- session为null
- session为null
- 会话不为空
- session为null
每次继续遍历代码时,只有当它开始执行Default.aspx
及其代码隐藏时,我才有可用的会话。 我实际上在Firefox中打开了网页,并监控网络请求。 第一个请求是https://localhost/Foo/
。
接下来我在Application_BeginRequest
设置了一个断点,并得到以下事件:
- 的BeginRequest
- 的AcquireRequestState
- 的BeginRequest
- 的AcquireRequestState
- 的BeginRequest
- AcquireRequestState(会话不为空)
- 执行Default.aspx(/ Foo返回对浏览器的响应)
- 的BeginRequest
- AcquireRequestState(会话再次为null)
在#9浏览器中的AJAX请求https://localhost:54859/8fad4e71e57a4caebe1c6ed7af6f583a/arterySignalR/poll?transport=longPolling&connectionToken=...&messageId=...&requestUrl=http%3A%2F%2Flocalhost%2FFoo%2F&browserName=Firefox&userAgent=Mozilla%2F5.0+(Windows+NT+6.1%3B+WOW64%3B+rv%3A41.0)+Gecko%2F20100101+Firefox%2F41.0&tid=4&_=1445346977956
正在等待响应。
我找到了关于通过显式URL提供页面与提供默认文档之间的区别的讨论 。
使用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"; } }
发生的事情是,在将请求传输到页面之前发生的某些事件会触发此事件。 同样,此事件可以由ASPX以外的页面引发。 我想你需要做一些事情:
我认为您的请求url不包含“.aspx”,对吧?
IIS7 +版本的配置whitch在认为请求处理程序不是managedHandler时不会使用“SessionStateModule”
所以解决方案很简单
找到您的web.config,然后添加该属性
....
runAllManagedModulesForAllRequests =“true”告诉asp.net无论如何都要使用所有模块
希望有帮助
当资源有编译错误时,即使在Application_PostAcquireRequestState中,会话也将为null
上述就是C#学习教程:在浏览器中加载虚拟目录名时,会话在AcquireRequestState中为空,但在加载Default.aspx时不为null分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/985027.html