我可以从 HTTPModule 访问会话状态吗?

发布于 2024-07-09 04:04:09 字数 408 浏览 4 评论 0原文

我确实可以从 HTTPModule 中更新用户的会话变量,但从我所看到的来看,这是不可能的。

更新:我的代码当前正在 OnBeginRequest () 事件处理程序内运行。

更新:根据迄今为止收到的建议,我尝试将其添加到 HTTPModule 中的 Init () 例程中:

AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute

但在我的 OnPreRequestHandlerExecute 例程中,会话状态仍然不可用!

谢谢,如果我遗漏了什么,请道歉!

I could really do with updating a user's session variables from within my HTTPModule, but from what I can see, it isn't possible.

UPDATE: My code is currently running inside the OnBeginRequest () event handler.

UPDATE: Following advice received so far, I tried adding this to the Init () routine in my HTTPModule:

AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute

But in my OnPreRequestHandlerExecute routine, the session state is still unavailable!

Thanks, and apologies if I'm missing something!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

ゝ杯具 2024-07-16 04:04:09

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,
// regardless 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; }
      }
   }
}

Found this over on the 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,
// regardless 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; }
      }
   }
}
芯好空 2024-07-16 04:04:09

HttpContext.Current.Session 应该可以正常工作,假设您的 HTTP 模块未处理之前发生的任何管道事件会话状态正在初始化...

编辑,在注释中澄清后:处理 BeginRequest 事件,Session 对象确实仍然为 null/Nothing,因为它还没有被 ASP.NET 运行时初始化。 要解决此问题,请将处理代码移至 PostAcquireRequestState -- 我喜欢 PreRequestHandlerExecute< /a> 对于我自己来说,因为所有低级工作几乎都在这个阶段完成,但您仍然抢先进行任何正常处理。

HttpContext.Current.Session should Just Work, assuming your HTTP Module isn't handling any pipeline events that occur prior to the session state being initialized...

EDIT, after clarification in comments: when handling the BeginRequest event, the Session object will indeed still be null/Nothing, as it hasn't been initialized by the ASP.NET runtime yet. To work around this, move your handling code to an event that occurs after PostAcquireRequestState -- I like PreRequestHandlerExecute for that myself, as all low-level work is pretty much done at this stage, but you still pre-empt any normal processing.

迷路的信 2024-07-16 04:04:09

可以在 PreRequestHandlerExecute 处理程序中访问 IHttpModule 中的 HttpContext.Current.Session

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();
        }
...
}

Accessing the HttpContext.Current.Session in a IHttpModule can be done in the PreRequestHandlerExecute handler.

PreRequestHandlerExecute: "Occurs just before ASP.NET starts executing an event handler (for example, a page or an XML Web service)." This means that before an 'aspx' page is served this event gets executed. The 'session state' is available so you can knock yourself out.

Example:

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();
        }
...
}
分分钟 2024-07-16 04:04:09

如果您在托管应用程序中编写普通的基本 HttpModule,并希望通过页面或处理程序将其应用于 ASP.NET 请求,则只需确保在会话创建后的生命周期中使用事件即可。 我通常会去 PreRequestHandlerExecute 而不是 Begin_Request。 mdb 在他的编辑中有正确的内容。

最初列为回答问题的较长代码片段有效,但比最初的问题复杂且广泛。 当内容来自没有可用的 ASP.net 处理程序(您可以在其中实现 IRequiresSessionState 接口)时,它将处理这种情况,从而触发会话机制以使其可用。 (就像磁盘上的静态 gif 文件)。 它基本上是设置一个虚拟处理程序,然后仅实现该接口以使会话可用。

如果您只需要代码的会话,只需选择要在模块中处理的正确事件即可。

If you're writing a normal, basic HttpModule in a managed application that you want to apply to asp.net requests through pages or handlers, you just have to make sure you're using an event in the lifecycle after session creation. PreRequestHandlerExecute instead of Begin_Request is usually where I go. mdb has it right in his edit.

The longer code snippet originally listed as answering the question works, but is complicated and broader than the initial question. It will handle the case when the content is coming from something that doesn't have an ASP.net handler available where you can implement the IRequiresSessionState interface, thus triggering the session mechanism to make it available. (Like a static gif file on disk). It's basically setting a dummy handler that then just implements that interface to make the session available.

If you just want the session for your code, just pick the right event to handle in your module.

沩ん囻菔务 2024-07-16 04:04:09

从 .NET 4.0 开始,不需要使用 IHttpHandler 来加载会话状态(就像最受支持的答案中的一个)。 有一种方法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()
        {
        }
    }
}

Since .NET 4.0 there is no need for this hack with IHttpHandler to load Session state (like one in most upvoted answer). There is a method HttpContext.SetSessionStateBehavior to define needed session behaviour.
If Session is needed on all requests set runAllManagedModulesForAllRequests to true in web.config HttpModule declaration, but be aware that there is a significant performance cost running all modules for all requests, so be sure to use preCondition="managedHandler" if you don't need Session for all requests.
For future readers here is a complete example:

web.config declaration - invoking HttpModule for all requests:

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
        <add name="ModuleWithSessionAccess" type="HttpModuleWithSessionAccess.ModuleWithSessionAccess, HttpModuleWithSessionAccess"/>
    </modules>
</system.webServer>

web.config declaration - invoking HttpModule only for managed requests:

<system.webServer>
    <modules>
        <add name="ModuleWithSessionAccess" type="HttpModuleWithSessionAccess.ModuleWithSessionAccess, HttpModuleWithSessionAccess" preCondition="managedHandler"/>
    </modules>
</system.webServer>

IHttpModule implementation:

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"] = 
quot;Random value: {new Random().Next()}";
            }
        }

        public void Dispose()
        {
        }
    }
}
沙与沫 2024-07-16 04:04:09

尝试一下:在类 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");
    }
}

Try it: in class MyHttpModule declare:

private HttpApplication contextapp;

Then:

public void Init(HttpApplication application)
{
     //Must be after AcquireRequestState - the session exist after RequestState
     application.PostAcquireRequestState += new EventHandler(MyNewEvent);
     this.contextapp=application;
}  

And so, in another method (the event) in the same class:

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");
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文