我可以从我的HTTPModule中更新用户的会话变量,但从我看到的情况来看,这是不可能的。
更新:我的代码当前正在OnBeginRequest ()
事件处理程序中运行。
更新:根据目前为止收到的建议,我尝试将其添加到HTTPModule中的Init ()
例程中:
AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute
但在我的OnPreRequestHandlerExecute
例程中,会话状态仍然不可用!
谢谢,如果我错过了什么,请道歉!
答案 0 :(得分:80)
在ASP.NET forums上找到了这个:
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; }
}
}
}
答案 1 :(得分:39)
HttpContext.Current.Session应该正常工作,假设您的HTTP模块没有处理在初始化会话状态之前发生的任何pipeline events ...
编辑,在评论中澄清:处理BeginRequest event时,Session对象确实仍然是null / Nothing,因为它还没有被ASP.NET运行时初始化。要解决此问题,请将处理代码移至PostAcquireRequestState之后发生的事件 - 我自己也喜欢PreRequestHandlerExecute,因为在此阶段所有的低级工作都已完成,但您仍然抢先任何正常处理。
答案 2 :(得分:15)
可以在HttpContext.Current.Session
处理程序中访问IHttpModule
中的PreRequestHandlerExecute
。
PreRequestHandlerExecute :“在ASP.NET开始执行事件处理程序之前发生(例如,页面或XML Web服务)。”这意味着在提供'aspx'页面之前,此事件将被执行。 “会话状态”可用,因此您可以将自己淘汰出局。
示例:
public class SessionModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += BeginTransaction;
context.EndRequest += CommitAndCloseSession;
context.PreRequestHandlerExecute += PreRequestHandlerExecute;
}
public void Dispose() { }
public void PreRequestHandlerExecute(object sender, EventArgs e)
{
var context = ((HttpApplication)sender).Context;
context.Session["some_sesion"] = new SomeObject();
}
...
}
答案 3 :(得分:12)
如果您在要通过页面或处理程序应用于asp.net请求的托管应用程序中编写正常的基本HttpModule,则只需确保在创建会话后在生命周期中使用事件。 PreRequestHandlerExecute而不是Begin_Request通常是我去的地方。 mdb在他的编辑中是正确的。
最初列为回答问题的较长代码段有效,但比初始问题复杂且广泛。当内容来自没有ASP.net处理程序的内容时,它将处理这种情况,您可以在其中实现IRequiresSessionState接口,从而触发会话机制使其可用。 (就像磁盘上的静态gif文件一样)。它基本上是设置一个虚拟处理程序,然后只是实现该接口以使会话可用。
如果您只想要代码的会话,只需选择要在您的模块中处理的正确事件。
答案 4 :(得分:0)
尝试一下:在MyHttpModule类中声明:
private HttpApplication contextapp;
然后:
public void Init(HttpApplication application)
{
//Must be after AcquireRequestState - the session exist after RequestState
application.PostAcquireRequestState += new EventHandler(MyNewEvent);
this.contextapp=application;
}
所以,在同一个类的另一个方法(事件)中:
public void MyNewEvent(object sender, EventArgs e)
{
//A example...
if(contextoapp.Context.Session != null)
{
this.contextapp.Context.Session.Timeout=30;
System.Diagnostics.Debug.WriteLine("Timeout changed");
}
}
答案 5 :(得分:0)
从 .NET 4.0 开始,无需使用 IHttpHandler 进行此 hack 加载会话状态(就像最受好评的答案中的那样)。有一个方法 HttpContext.SetSessionStateBehavior 来定义所需的会话行为。
如果所有请求都需要 Session 在 web.config HttpModule 声明中将 runAllManagedModulesForAllRequests
设置为 true,但请注意运行所有请求的所有模块会产生显着的性能成本,因此请务必使用 preCondition="managedHandler"
如果您不需要 Session 来处理所有请求。
对于未来的读者,这里有一个完整的例子:
web.config 声明 - 为所有请求调用 HttpModule:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="ModuleWithSessionAccess" type="HttpModuleWithSessionAccess.ModuleWithSessionAccess, HttpModuleWithSessionAccess"/>
</modules>
</system.webServer>
web.config 声明 - 仅为托管请求调用 HttpModule:
<system.webServer>
<modules>
<add name="ModuleWithSessionAccess" type="HttpModuleWithSessionAccess.ModuleWithSessionAccess, HttpModuleWithSessionAccess" preCondition="managedHandler"/>
</modules>
</system.webServer>
IHttpModule 实现:
namespace HttpModuleWithSessionAccess
{
public class ModuleWithSessionAccess : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += Context_BeginRequest;
context.PreRequestHandlerExecute += Context_PreRequestHandlerExecute;
}
private void Context_BeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
app.Context.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}
private void Context_PreRequestHandlerExecute(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
if (app.Context.Session != null)
{
app.Context.Session["Random"] = $"Random value: {new Random().Next()}";
}
}
public void Dispose()
{
}
}
}