c# – 在浏览器中加载虚拟目录名时,AcquireRequestState中的会话为空,加载Default.aspx时,会话为空

前端之家收集整理的这篇文章主要介绍了c# – 在浏览器中加载虚拟目录名时,AcquireRequestState中的会话为空,加载Default.aspx时,会话为空前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个ASP.NET 4.0 WebForms应用程序.我需要访问HttpContext.Current.Session并在Global.asax中的AcquireRequestState事件(或其后的事件)中设置一个值,我发现了一个特殊的行为.

假设我在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 no NullReferenceException 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正在等待响应.

解决方法

我发现 a discussion关于通过其显式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";
    }
}

猜你在找的C#相关文章