ฉันสามารถเข้าถึงสถานะเซสชันจากโมดูล HTTPM ได้หรือไม่


85

ฉันสามารถอัปเดตตัวแปรเซสชันของผู้ใช้ได้จากภายในโมดูล HTTPM ของฉัน แต่จากสิ่งที่ฉันเห็นมันเป็นไปไม่ได้

อัปเดต:รหัสของฉันกำลังทำงานอยู่ในOnBeginRequest ()ตัวจัดการเหตุการณ์

อัปเดต:ตามคำแนะนำที่ได้รับจนถึงตอนนี้ฉันได้ลองเพิ่มสิ่งนี้ลงในInit ()รูทีนในโมดูล HTTPM ของฉัน:

AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute

แต่ในOnPreRequestHandlerExecuteกิจวัตรของฉันสถานะเซสชันยังไม่พร้อมใช้งาน!

ขอบคุณและขออภัยหากขาดอะไรไป!

คำตอบ:


83

พบสิ่งนี้ในฟอรัม 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; }
      }
   }
}

8
MS ควรแก้ไขสิ่งนี้! ... ถ้าฉันทำเครื่องหมายโมดูลว่าใช้ IRequiresSessionState ฉันไม่ควรต้องกระโดดผ่านห่วงเพื่อรับมัน ... (รหัสเซ็กซี่แน่นอน)
BigBlondeViking

6
รหัสที่ดี ฉันคิดว่าฉันต้องการสิ่งนี้ แต่ปรากฎว่าไม่ใช่ โค้ดนี้จะสิ้นสุดการโหลดเซสชันสำหรับทุกรูปภาพและทรัพยากรอื่น ๆ ที่ไม่ใช่เพจที่ผ่านเซิร์ฟเวอร์ ในกรณีของฉันฉันเพียงแค่ตรวจสอบว่าเซสชันเป็นโมฆะในเหตุการณ์ PostAcquireRequestState หรือไม่และส่งคืนหากเป็น
Abtin Forouzandeh

7
รหัสนี้มีประโยชน์หากทรัพยากรที่ร้องขอไม่จัดการสถานะเซสชัน สำหรับเพจ. aspx มาตรฐานเพียงแค่เพิ่มรหัสของคุณเพื่อเข้าถึงเซสชันบนตัวจัดการเหตุการณ์ PostAcquireRequestState สถานะเซสชันจะไม่พร้อมใช้งานบนตัวจัดการเหตุการณ์ BeginRequest เนื่องจากยังไม่ได้รับสถานะเซสชัน
JCallico

3
มันใช้ไม่ได้ในกรณีของฉัน ฉันได้รับ "สถานะเซสชันไม่พร้อมใช้งานในบริบทนี้" เมื่อมีคำขอพยายามเข้าถึงไฟล์แบบคงที่ ความช่วยเหลือใด ๆ
maxisam

3
เพื่อให้สามารถทำงานกับไฟล์แบบคงที่ได้นอกจากนี้ฉันจึงลงทะเบียนโมดูลเซสชันอีกครั้ง (ใน web.config) โดยการลบ preCondition = "managedHandler" (<remove name = "Session" /> <add name = " Session "type =" System.Web.SessionState.SessionStateModule "/>)
nlips

39

HttpContext.Current.Sessionควรจะใช้งานได้โดยสมมติว่าโมดูล HTTP ของคุณไม่ได้จัดการกับเหตุการณ์ไปป์ไลน์ใด ๆที่เกิดขึ้นก่อนที่สถานะเซสชันจะเริ่มต้น ...

แก้ไขหลังจากการชี้แจงในข้อคิดเห็น: เมื่อจัดการกับเหตุการณ์ BeginRequestวัตถุเซสชันจะยังคงเป็นโมฆะ / ไม่มีอะไรเนื่องจากยังไม่ได้เริ่มต้นโดยรันไทม์ ASP.NET ในการแก้ไขปัญหานี้ให้ย้ายรหัสการจัดการของคุณไปยังเหตุการณ์ที่เกิดขึ้นหลังจากPostAcquireRequestState - ฉันชอบPreRequestHandlerExecuteสำหรับสิ่งนั้นด้วยตัวเองเนื่องจากงานระดับต่ำทั้งหมดทำได้ค่อนข้างมากในขั้นตอนนี้ แต่คุณยังคงทำการประมวลผลตามปกติไว้ล่วงหน้า


ขออภัยที่ไม่มีในโมดูล HTTPM - "การอ้างอิงวัตถุไม่ได้ตั้งค่าเป็นอินสแตนซ์ของออบเจ็กต์"
Chris Roberts

ฉันกำลังประมวลผล 'OnBeginRequest'?
Chris Roberts

ขอบคุณสำหรับการอัพเดท. หากฉันจัดการมันในเหตุการณ์ระดับแอปพลิเคชันทำไมฉันไม่ดำเนินการทั้งหมดที่ระดับแอปพลิเคชันแทนที่จะใช้โมดูล HTTPM
Chris Roberts

1
PostAcquireRequeststate ไม่ใช่ 'เหตุการณ์ระดับแอปพลิเคชัน': หากคำขอ HTTP ได้รับการจัดการโดยตัวจัดการบริการเว็บคุณจะยังคงเห็นอยู่ในโมดูล HTTP ของคุณ แต่ไม่ใช่ใน Global.asax ...
mdb

สิ่งนี้ดูเหมือนจะไม่ได้ผลสำหรับฉัน รหัสต่อไปนี้มักจะทำให้เกิดข้อยกเว้น 'สถานะเซสชันไม่พร้อมใช้งานในบริบทนี้' ในความเป็นจริงมันขัดข้อง VS ดีบักเกอร์ค่อนข้างน่าตื่นเต้น context.PreRequestHandlerExecute + = (ผู้ส่ง, args) => Console.Write (((HttpApplication) ผู้ส่ง ).Session ["test"];
cbp

15

การเข้าถึงHttpContext.Current.Sessionin a IHttpModuleสามารถทำได้ในPreRequestHandlerExecuteตัวจัดการ

PreRequestHandlerExecute : "เกิดขึ้นก่อนที่ ASP.NET จะเริ่มเรียกใช้ตัวจัดการเหตุการณ์ (ตัวอย่างเช่นเพจหรือบริการเว็บ XML)" ซึ่งหมายความว่าก่อนหน้าที่จะแสดงหน้า "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();
        }
...
}

ฉันลองแล้วคุณจะได้รับเซสชันแน่นอน แต่ดูเหมือนว่า RequestHeader จะไม่เต็มโดยเฉพาะ HeaderContentType
Matthias Müller

12

หากคุณกำลังเขียน HttpModule พื้นฐานปกติในแอปพลิเคชันที่มีการจัดการที่คุณต้องการใช้กับคำขอ asp.net ผ่านเพจหรือตัวจัดการคุณต้องแน่ใจว่าคุณกำลังใช้เหตุการณ์ในวงจรชีวิตหลังจากการสร้างเซสชัน PreRequestHandlerExecute แทน Begin_Request มักจะเป็นที่ที่ฉันไป mdb มีสิทธิ์ในการแก้ไขของเขา

ข้อมูลโค้ดที่ยาวกว่าเดิมระบุว่าตอบคำถามใช้ได้ แต่ซับซ้อนและกว้างกว่าคำถามเริ่มต้น จะจัดการกรณีนี้เมื่อเนื้อหามาจากสิ่งที่ไม่มีตัวจัดการ ASP.net ซึ่งคุณสามารถใช้อินเทอร์เฟซ IRequiresSessionState ได้ดังนั้นจึงเรียกใช้กลไกเซสชันเพื่อให้พร้อมใช้งาน (เช่นไฟล์ gif แบบคงที่บนดิสก์) โดยพื้นฐานแล้วเป็นการตั้งค่าตัวจัดการดัมมี่จากนั้นเพียงแค่ใช้อินเทอร์เฟซนั้นเพื่อให้เซสชันพร้อมใช้งาน

หากคุณต้องการเพียงแค่เซสชันสำหรับโค้ดของคุณเพียงแค่เลือกเหตุการณ์ที่เหมาะสมเพื่อจัดการในโมดูลของคุณ


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");
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.