2008-11-09 4 views
77

Я мог бы действительно сделать с обновлением переменных сеанса пользователя из моего HTTPModule, но из того, что я вижу, это невозможно.Могу ли я получить доступ к состоянию сеанса из HTTPModule?

UPDATE: Мой код в настоящее время запущен внутри обработчика событий OnBeginRequest().

UPDATE: После консультации получил до сих пор, я попытался добавить это к Init() рутине в моем HttpModule:

AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute

Но в моем OnPreRequestHandlerExecute рутины, состояние сеанса все еще недоступен!

Спасибо и извини, если я что-то упустил!

ответ

79

Нашел над на 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; } 
     } 
    } 
} 
36

HttpContext.Current.Session должен просто работать, предполагается, что ваш HTTP модуль не обрабатывает любые pipeline events, которые происходят до состояния сеанса инициализируемого ...

EDIT, после уточнения в комментариях: при обращении с BeginRequest event, объект Session будет по-прежнему оставаться null/Nothing, поскольку он еще не был инициализирован временем выполнения ASP.NET. Чтобы обойти это, переместите свой код обработки в событие, которое происходит после PostAcquireRequestState. Мне нравится PreRequestHandlerExecute, потому что все низкоуровневые работы на этом этапе в значительной степени выполняются, но вы все равно упреждаете любую обычную обработку.

+0

К сожалению, это недоступно в HTTPModule - «Ссылка на объект не установлена ​​в экземпляр объекта». – 2008-11-09 19:39:03

+0

Я обрабатываю 'OnBeginRequest'? – 2008-11-09 19:39:53

+0

Спасибо за обновление. Если я обрабатываю его в событии уровня приложения, почему бы мне просто не выполнять всю обработку на уровне приложения вместо использования HTTPModule? – 2008-11-09 19:47:47

11

Если вы пишете нормальный, основной HttpModule в управляемом приложении, которое вы хотите применить к запросам asp.net через страницу или обработчик, вы просто чтобы убедиться, что вы используете событие в жизненном цикле после создания сеанса. PreRequestHandlerExecute вместо Begin_Request обычно находится там, где я иду. mdb имеет право в его редактировании.

Более длинный фрагмент кода, первоначально указанный в ответе на вопрос, работает, но сложный и шире, чем исходный вопрос. Он будет обрабатывать случай, когда контент поступает из того, что не имеет обработчика ASP.net, где вы можете реализовать интерфейс IRequiresSessionState, тем самым инициируя механизм сеанса, чтобы сделать его доступным. (Как статический файл gif на диске). Это в основном настройка фиктивного обработчика, который затем реализует этот интерфейс, чтобы сделать сеанс доступным.

Если вы просто хотите сеанс для своего кода, просто выберите подходящее событие для обработки в своем модуле.

12

Доступ к HttpContext.Current.Session в 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(); 
     } 
... 
} 
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"); 
    } 
}