代码之家  ›  专栏  ›  技术社区  ›  Chris Roberts

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

  •  84
  • Chris Roberts  · 技术社区  · 16 年前

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

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

    Init () 我的HTTPModule中的例程:

    AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute

    OnPreRequestHandlerExecute 例行程序,会话状态仍然不可用!

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

    5 回复  |  直到 16 年前
        1
  •  84
  •   Mesidin    4 年前

    在街上发现的 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; }
          }
       }
    }
    
        2
  •  39
  •   mdb    16 年前

    HttpContext.Current.Session pipeline events 在初始化会话状态之前发生的。。。

    在注释中澄清后编辑:在处理 BeginRequest event ,会话对象实际上仍然是null/Nothing,因为它还没有被ASP.NET运行时初始化。要解决此问题,请将处理代码移动到发生在 PostAcquireRequestState PreRequestHandlerExecute 对于我自己来说,因为所有的低级工作都在这个阶段完成了,但是您仍然会抢占任何正常的处理。

        3
  •  15
  •   Bert Persyn    13 年前

    访问 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();
            }
    ...
    }
    
        4
  •  12
  •   Rob    15 年前

    如果要在托管应用程序中编写一个普通的、基本的HttpModule,并希望通过页面或处理程序将其应用于asp.net请求,则只需确保在创建会话后在生命周期中使用事件即可。PreRequestHandlerExecute而不是Begin_请求通常是我要去的地方。mdb在他的编辑中有它的权利。

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

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

        5
  •  0
  •   aTest    9 年前

    尝试:在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");
        }
    }
    
        6
  •  0
  •   Antonio Bakula    3 年前

    自从.NET4.0以来,IHttpHandler的这种攻击就没有必要加载会话状态(就像大多数上浮答案中的一样)。有一种方法 HttpContext.SetSessionStateBehavior 如果所有请求集上都需要会话 runAllManagedModulesForAllRequests preCondition="managedHandler" 如果您不需要所有请求的会话。 对于未来的读者,这里有一个完整的示例:

    <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>
    

    IHTTP模块实现:

    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()
            {
            }
        }
    }