Tôi có thể truy cập trạng thái phiên từ HTTPModule không?


85

Tôi thực sự có thể làm với việc cập nhật các biến phiên của người dùng từ bên trong HTTPModule của mình, nhưng từ những gì tôi có thể thấy, điều đó là không thể.

CẬP NHẬT: Mã của tôi hiện đang chạy bên trongOnBeginRequest () trình xử lý sự kiện.

CẬP NHẬT: Theo lời khuyên nhận được cho đến nay, tôi đã thử thêm điều này vào Init ()quy trình trong HTTPModule của mình:

AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute

Nhưng trong tôi OnPreRequestHandlerExecute thói quen , trạng thái phiên vẫn không khả dụng!

Cảm ơn và xin lỗi nếu tôi thiếu điều gì đó!

Câu trả lời:


83

Tìm thấy điều này trên diễn đàn 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 nên để khắc phục điều này ... nếu tôi đánh dấu một Module như thực hiện IRequiresSessionState, tôi nên không cần phải nhảy qua một hoop để có được nó ... (mã sexy thực sự)
BigBlondeViking

6
Mã đẹp. Tôi đã nghĩ rằng tôi sẽ cần thứ này, nhưng hóa ra không phải. Mã này kết thúc tải phiên cho mọi hình ảnh và tài nguyên không phải trang khác đi qua máy chủ. Trong trường hợp của tôi, tôi chỉ cần kiểm tra xem phiên có rỗng trong sự kiện PostAcquireRequestState không và trả về nếu có.
Abtin Forouzandeh

7
Mã này hữu ích nếu tài nguyên được yêu cầu không xử lý trạng thái phiên. Đối với các trang .aspx tiêu chuẩn, chỉ cần thêm mã của bạn truy cập phiên trên trình xử lý sự kiện PostAcquireRequestState. Trạng thái phiên sẽ không khả dụng trên bất kỳ trình xử lý sự kiện BeginRequest nào vì trạng thái phiên chưa được lấy.
JCallico

3
Nó không hoạt động trong trường hợp của tôi. Tôi nhận được "Trạng thái phiên không khả dụng trong ngữ cảnh này." khi có yêu cầu cố gắng truy cập tệp tĩnh. Bất kỳ giúp đỡ?
maxisam

3
Để điều này hoạt động trên các tệp tĩnh, ngoài ra, tôi phải đăng ký lại mô-đun phiên (trong web.config) bằng cách xóa preCondition = "ManagedHandler" (<remove name = "Session" /> <add name = " Phiên "type =" System.Web.SessionState.SessionStateModule "/>)
hết

39

HttpContext.Current.Session chỉ nên hoạt động, giả sử Mô-đun HTTP của bạn không xử lý bất kỳ sự kiện đường ống nào xảy ra trước khi trạng thái phiên được khởi tạo ...

CHỈNH SỬA, sau khi làm rõ trong phần nhận xét: khi xử lý sự kiện BeginRequest , đối tượng Session sẽ thực sự vẫn là null / Nothing, vì nó chưa được khởi tạo bởi thời gian chạy ASP.NET. Để giải quyết vấn đề này, hãy di chuyển mã xử lý của bạn sang một sự kiện xảy ra sau PostAcquireRequestState - Tôi thích PreRequestHandlerExecute cho bản thân mình, vì tất cả công việc cấp thấp được thực hiện khá nhiều ở giai đoạn này, nhưng bạn vẫn thực hiện trước bất kỳ xử lý bình thường nào.


Rất tiếc, điều đó không có sẵn trong HTTPModule - "Tham chiếu đối tượng không được đặt thành một phiên bản của đối tượng."
Chris Roberts

Tôi đang xử lý 'OnBeginRequest'?
Chris Roberts

Cảm ơn các cập nhật. Nếu tôi xử lý nó trong một sự kiện ở cấp Ứng dụng, tại sao tôi không thực hiện tất cả quá trình xử lý của mình ở cấp ứng dụng thay vì sử dụng HTTPModule?
Chris Roberts

1
PostAcquireRequeststate không phải là 'sự kiện cấp ứng dụng': ví dụ: nếu yêu cầu HTTP được xử lý bởi trình xử lý dịch vụ web, bạn sẽ vẫn thấy nó trong mô-đun HTTP của mình, nhưng không phải trong Global.asax ...
mdb

Điều này dường như không hoạt động đáng tin cậy đối với tôi. Đoạn mã sau thường sẽ gây ra ngoại lệ 'Trạng thái phiên không khả dụng trong ngữ cảnh này'. Trên thực tế, nó làm sập trình gỡ lỗi VS khá ngoạn mục. context.PreRequestHandlerExecute + = (sender, args) => Console.Write (((HttpApplication) sender) .Session ["test"];
cbp

15

Việc truy cập HttpContext.Current.Sessionvào một IHttpModulecó thể được thực hiện trong PreRequestHandlerExecutetrình xử lý.

PreRequestHandlerExecute : "Xảy ra ngay trước khi ASP.NET bắt đầu thực thi một trình xử lý sự kiện (ví dụ: một trang hoặc một dịch vụ Web XML)." Điều này có nghĩa là trước khi trang 'aspx' được phân phát, sự kiện này sẽ được thực thi. 'Trạng thái phiên' có sẵn để bạn có thể loại bỏ chính mình.

Thí dụ:

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

Tôi đã thử điều này và bạn thực sự nhận được Phiên. Nhưng có vẻ như RequestHeader không hoàn toàn ở đó, đặc biệt là HeaderContentType
Matthias Müller

12

Nếu bạn đang viết một HttpModule cơ bản, bình thường trong một ứng dụng được quản lý mà bạn muốn áp dụng cho các yêu cầu asp.net thông qua các trang hoặc trình xử lý, bạn chỉ cần đảm bảo rằng bạn đang sử dụng một sự kiện trong vòng đời sau khi tạo phiên. PreRequestHandlerExecute thay vì Begin_Request thường là nơi tôi đến. mdb có nó ngay trong bản chỉnh sửa của mình.

Đoạn mã dài hơn được liệt kê ban đầu là trả lời câu hỏi hoạt động, nhưng phức tạp và rộng hơn câu hỏi ban đầu. Nó sẽ xử lý trường hợp khi nội dung đến từ thứ gì đó không có sẵn trình xử lý ASP.net, nơi bạn có thể triển khai giao diện IRequiresSessionState, do đó kích hoạt cơ chế phiên để làm cho nó khả dụng. (Giống như tệp gif tĩnh trên đĩa). Về cơ bản, nó thiết lập một trình xử lý giả, sau đó chỉ cần cài đặt giao diện đó để làm cho phiên có sẵn.

Nếu bạn chỉ muốn phiên cho mã của mình, chỉ cần chọn sự kiện phù hợp để xử lý trong mô-đun của bạn.


0

Hãy thử nó: trong lớp MyHttpModule khai báo:

private HttpApplication contextapp;

Sau đó:

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

Và như vậy, trong một phương thức khác (sự kiện) trong cùng một lớp:

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");
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.