在我的程序中,我正在尝试在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";
}
}
答案 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";
}