路由请求时 HttpContext.Current.Session 为空

Posted

技术标签:

【中文标题】路由请求时 HttpContext.Current.Session 为空【英文标题】:HttpContext.Current.Session is null when routing requests 【发布时间】:2010-09-18 02:21:39 【问题描述】:

没有路由,HttpContext.Current.Session 就在那里,所以我知道StateServer 正在工作。当我路由我的请求时,HttpContext.Current.Session 在路由页面中是null。我在 IIS 7.0 上使用 .NET 3.5 sp1,没有 MVC 预览。似乎AcquireRequestState 在使用路由时从未被触发,因此会话变量不会被实例化/填充。

当我尝试访问 Session 变量时,出现以下错误:

base System.Runtime.InteropServices.ExternalException = "Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive. Please also make sure that System.Web.SessionStateModule or a custom session state module is included in the <configuration>.

在调试时,我还收到HttpContext.Current.Session 在该上下文中不可访问的错误。

--

我的web.config 看起来像这样:

<configuration>
  ...
  <system.web>
    <pages enableSessionState="true">
      <controls>
        ...
      </controls>
    </pages>
    ...
  </system.web>
  <sessionState cookieless="AutoDetect" mode="StateServer" timeout="22" />
  ...
</configuration>

这是 IRouteHandler 的实现:

public class WebPageRouteHandler : IRouteHandler, IRequiresSessionState

    public string m_VirtualPath  get; private set; 
    public bool m_CheckPhysicalUrlAccess  get; set; 

    public WebPageRouteHandler(string virtualPath) : this(virtualPath, false)
    
    
    public WebPageRouteHandler(string virtualPath, bool checkPhysicalUrlAccess)
    
        m_VirtualPath = virtualPath;
        m_CheckPhysicalUrlAccess = checkPhysicalUrlAccess;
    

    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    
        if (m_CheckPhysicalUrlAccess
            && !UrlAuthorizationModule.CheckUrlAccessForPrincipal(
                   m_VirtualPath,
                   requestContext.HttpContext.User,
                   requestContext.HttpContext.Request.HttpMethod))
        
            throw new SecurityException();
        

        string var = String.Empty;
        foreach (var value in requestContext.RouteData.Values)
        
            requestContext.HttpContext.Items[value.Key] = value.Value;
        

        Page page = BuildManager.CreateInstanceFromVirtualPath(
                        m_VirtualPath, 
                        typeof(Page)) as Page;// IHttpHandler;

        if (page != null)
        
            return page;
        
        return page;
    

我也尝试将 EnableSessionState="True" 放在 aspx 页面的顶部,但仍然没有。

有什么见解吗?我应该写另一个实现IRequiresSessionStateHttpRequestHandler 吗?

谢谢。

【问题讨论】:

【参考方案1】:

知道了。相当愚蠢,实际上。在我像这样删除并添加 SessionStateModule 后它起作用了:

<configuration>
  ...
  <system.webServer>
    ...
    <modules>
      <remove name="Session" />
      <add name="Session" type="System.Web.SessionState.SessionStateModule"/>
      ...
    </modules>
  </system.webServer>
</configuration>

仅仅添加它是行不通的,因为“会话”应该已经在 machine.config 中定义了。

现在,我想知道这是否是通常的做法。看起来肯定不是这样,因为它看起来很粗糙......

【讨论】:

谢谢。它很好地解决了我的问题——事实证明,生产服务器需要它,而不是开发机器。 那是 ins@ne!谢谢。这也修复了我的“TempData”(mvc razor)值也不会消失(因为 TempData 使用 Session)。圣钼。 我遇到了 TempData 值消失的问题,但这并没有解决。 刚刚修复了我的 TempData 的问题。我必须在 web.config 上更改 sessionState 以使用 StateServer 而不是默认的 InProc【参考方案2】:

只需在 web.config 中将属性 runAllManagedModulesForAllRequests="true" 添加到 system.webServer\modules 即可。

此属性在 MVC 和动态数据项目中默认启用。

【讨论】:

太棒了!这是我所追求的答案.. 比公认的要好得多。 阅读一些 shanselman 以了解为什么 rammfar 对您(服务器的)健康有害:hanselman.com/blog/…【参考方案3】:

runAllManagedModulesForAllRequests=true 实际上是一个非常糟糕的解决方案。这将我的应用程序的加载时间增加了 200%。更好的解决方案是手动删除和添加会话对象,并避免一起运行所有托管模块属性。

【讨论】:

【参考方案4】:

这些解决方案都不适合我。我将以下方法添加到global.asax.cs 然后 Session 不为空:

protected void Application_PostAuthorizeRequest()

    HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);

【讨论】:

为什么这有帮助? :^) @user2173353 对我来说,这很有帮助,因为我试图在 web.api 请求期间访问对象中的 SessionState。我认为它以前不起作用,因为 SessionState 未包含在该特定类型请求的 HttpContext 中。 @jaybro 是的,我现在也知道了,经过一些调查,我做到了。 WebAPI 默认禁用会话状态,如果您想使用它,您需要自己启用它。但是,如果您不将其用作ReadOnly,则用户请求将不会并行执行,因为同一用户的每个请求都会锁定会话状态字典以防止出现竞争条件。我尝试为每个端点设置不同的SessionStateBehavior,只在需要时使用Required,但框架对我不利。【参考方案5】:

@Bogdan Maxim 所说的。如果您不使用外部会话状态服务器,或者更改为使用 InProc。

<sessionState mode="InProc" timeout="20" cookieless="AutoDetect" />

查看here 了解有关 SessionState 指令的更多信息。

【讨论】:

如果我正常访问页面,SessionState 有效。如果我使用路由,则 HttpContext.Current.Session 为空。 部分似乎在配置中工作。【参考方案6】:

干得好!我一直有完全相同的问题。添加和删​​除 Session 模块对我来说也很完美。然而,它并没有被 HttpContext.Current.User 带回来,所以我用 FormsAuth 模块尝试了你的小技巧,果然成功了。

<remove name="FormsAuthentication" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule"/>

【讨论】:

【参考方案7】:

您似乎忘记在config文件中添加您的状态服务器地址。

 <sessionstate mode="StateServer" timeout="20" server="127.0.0.1" port="42424" />

【讨论】:

试过了,还是一样。它的默认值并不重要:"tcpip=loopback:42424"(msdn.microsoft.com/en-us/library/…) 我怀疑问题出在会话提供程序中,因为它在没有路由的情况下工作。【参考方案8】:

如果正常访问页面,配置部分似乎正常工作。我已经尝试了建议的其他配置,但问题仍然存在。

我怀疑问题出在会话提供程序中,因为它在没有路由的情况下也能工作。

【讨论】:

【参考方案9】:

我认为这部分代码会改变上下文。

 Page page = BuildManager.CreateInstanceFromVirtualPath(
                        m_VirtualPath, 
                        typeof(Page)) as Page;// IHttpHandler;

这部分代码也没用:

 if (page != null)
 
     return page;
 
 return page;

无论是否为空,它都会返回页面。

【讨论】:

感谢您的提醒。在尝试了很多东西之后,那是一些残留的代码。 :D【参考方案10】:

我在会话适配器中缺少对 System.web.mvc dll 的引用,并且添加相同的内容解决了问题。

希望它能帮助其他人经历同样的情况。

【讨论】:

这是什么意思?执行此操作的步骤是什么? 抱歉,我无法理解您的问题。你在说什么步骤?我通过右键单击 Visual Studio 内的 mvc 项目上的引用添加了对“System.web.mvc dll”的引用【参考方案11】:

更好的解决方案是

runAllManagedModulesForAllRequest 在删除和重新插入会话模块方面是一件聪明的事情。

说吧。

【讨论】:

请阅读本文以了解为什么这不是一个聪明的解决方案:hanselman.com/blog/…

以上是关于路由请求时 HttpContext.Current.Session 为空的主要内容,如果未能解决你的问题,请参考以下文章

HttpContext.Current.Items用途

HttpContext.Current.Items的用途

WCF REST HttpContext.Current 异步/等待

使用 IAuthenticationFilter 时 HttpContext.Current 为空

缓存 HttpContext.Current.Cache和HttpRuntime.Cache的区别

页面间传值的困惑