会话在IHttpModule中不可用

时间:2014-01-16 07:17:14

标签: c# asp.net

在我的程序中,我正在尝试在IHttpModule中使用会话变量。这是我的代码。这在VS 2010开发服务器中运行良好。但是,当我尝试在IIS7中进行调试时,它会显示异常System.Web.HttpException: Session state is not available in this context 那么为什么会话在IIS 7中不可用,但在开发服务器中。

using System;
using System.Web;

public class Globalizer : IHttpModule
{    
  public void Init(HttpApplication context)
  {
    context.AcquireRequestState += new EventHandler(setLanguage);
  }

  public void Dispose(){}

  public void setLanguage(Object sender, EventArgs i_eventArgs)
  {
    HttpApplication http_application = sender as HttpApplication;     
    http_application.Session["language"] = "test";

  }
}

4 个答案:

答案 0 :(得分:1)

您只需要实施IRequiresSessionState

所以你的代码应该是这样的:

public class Globalizer : IHttpModule, IRequiresSessionState

如果您使用的只是读取会话(并且从不更新它们),那么您应该使用IReadOnlySessionState,因为这最后不会锁定会话状态,因此,您将不会有并发请求。)

答案 1 :(得分:0)

如果可能,请将处理程序移至PostAcquireRequestState处理程序:

  

在获取与当前请求关联的请求状态(例如,会话状态)时发生。

(或者甚至是后来的事件)

SessionStateModule本身会加载会话状态以响应AcquireRequestState事件 - 所以此刻,您要依赖于您的模块或会话状态模块的处理程序是否首先启动。

答案 2 :(得分:0)

在ASP.NET论坛上发现了这个:

using System;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.Diagnostics;

// This code demonstrates how to make session state available in HttpModule,
// regradless of requested resource.
// author: Tomasz Jastrzebski

public class MyHttpModule : IHttpModule
{
   public void Init(HttpApplication application)
   {
      application.PostAcquireRequestState += new EventHandler(Application_PostAcquireRequestState);
      application.PostMapRequestHandler += new EventHandler(Application_PostMapRequestHandler);
   }

   void Application_PostMapRequestHandler(object source, EventArgs e)
   {
      HttpApplication app = (HttpApplication)source;

      if (app.Context.Handler is IReadOnlySessionState || app.Context.Handler is IRequiresSessionState) {
         // no need to replace the current handler
         return;
      }

      // swap the current handler
      app.Context.Handler = new MyHttpHandler(app.Context.Handler);
   }

   void Application_PostAcquireRequestState(object source, EventArgs e)
   {
      HttpApplication app = (HttpApplication)source;

      MyHttpHandler resourceHttpHandler = HttpContext.Current.Handler as MyHttpHandler;

      if (resourceHttpHandler != null) {
         // set the original handler back
         HttpContext.Current.Handler = resourceHttpHandler.OriginalHandler;
      }

      // -> at this point session state should be available

      Debug.Assert(app.Session != null, "it did not work :(");
   }

   public void Dispose()
   {

   }

   // a temp handler used to force the SessionStateModule to load session state
   public class MyHttpHandler : IHttpHandler, IRequiresSessionState
   {
      internal readonly IHttpHandler OriginalHandler;

      public MyHttpHandler(IHttpHandler originalHandler)
      {
         OriginalHandler = originalHandler;
      }

      public void ProcessRequest(HttpContext context)
      {
         // do not worry, ProcessRequest() will not be called, but let's be safe
         throw new InvalidOperationException("MyHttpHandler cannot process requests.");
      }

      public bool IsReusable
      {
         // IsReusable must be set to false since class has a member!
         get { return false; }
      }
   }
}

答案 3 :(得分:0)

找到原因。

如果是因为AcquireRequestState触发所有文件,如CSS,JS,图像。那些文件没有会话。

解决方案:似乎有一种方法可以避免为所有请求调用IHttpModule。 cckck这个答案JS,Images and CSS getting intercepted by HTTPModule

但它对我不起作用。所以我使用HttpContext.Current.Session而不是HttpApplication.Session,并且每次在保存到会话之前检查Session是否为空。

如果有人知道,如何避免为IHttpModule以外的文件致电.aspx请在此处提供帮助。

这是最终代码

using System;
using System.Web;

public class Globalizer : IHttpModule
{    
  public void Init(HttpApplication context)
  {
    context.AcquireRequestState += new EventHandler(setLanguage);
  }

  public void Dispose(){}

  public void setLanguage(Object sender, EventArgs i_eventArgs)
  {
    if(HttpContext.Current.Session != null){
      HttpContext.Current.Session["language"] = "test";
    }

  }
}

修改:另一种方法是仅在请求来到.aspx文件时使用会话

HttpApplication http_application = sender as HttpApplication; 
HttpContext context = http_application.Context;
if(Path.GetExtension(context.Request.PhysicalPath) == ".aspx")
{
 HttpContext.Current.Session["language"] = "test";
 http_application.Session["language2"] = "test2";
}