2008-11-09 18 views
77

Podría realmente hacer la actualización de las variables de sesión de un usuario desde mi HTTPModule, pero por lo que puedo ver, no es posible.¿Puedo acceder al estado de la sesión desde un HTTPModule?

ACTUALIZACIÓN: Mi código se está ejecutando actualmente dentro del controlador de eventos OnBeginRequest().

ACTUALIZACIÓN: Siguiendo los consejos recibidos hasta ahora, he intentado añadir esto a la rutina Init() en mi HTTPModule:

AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute

Pero en mi rutina OnPreRequestHandlerExecute, el estado de la sesión aún no está disponible!

Gracias, y me disculpa si me falta algo!

Respuesta

79

encontrado este sobre en el 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; } 
     } 
    } 
} 
+0

Gracias -.?! este código resolvieron el problema –

+7

¡MS debería arreglar esto! ... si marcó un Módulo como implementación del IRequiresSessionState, no debería tener que saltar por un aro para obtenerlo ... (código atractivo en realidad) – BigBlondeViking

+4

Código agradable. Pensé que necesitaría esto, pero resulta que no. Este código termina cargando la sesión para cada imagen y otro recurso ajeno a la página que pasa por el servidor. En mi caso, simplemente compruebo si la sesión es nula en el evento PostAcquireRequestState y lo devuelvo si lo es. –

36

HttpContext.Current.Session debe apenas trabajo, asumiendo que su módulo HTTP no está manejando cualquier pipeline events que se producen antes del estado de la sesión siendo inicializado ...

EDITAR, después de la clarificación de los comentarios: al manipular el BeginRequest event, el objeto Session de hecho seguirá siendo nulo/Nothing, ya que aún no ha sido inicializado por el tiempo de ejecución de ASP.NET. Para evitar esto, mueva su código de manejo a un evento que ocurra después de PostAcquireRequestState - Me gusta PreRequestHandlerExecute para mí, ya que todo el trabajo de bajo nivel casi se realiza en esta etapa, pero todavía preautoriza cualquier procesamiento normal.

+0

Lamentablemente, no está disponible en el HTTPModule - "Referencia de objeto no configurada para una instancia de un objeto". –

+0

Estoy procesando 'OnBeginRequest'? –

+0

Gracias por la actualización. Si lo manejo en un evento de nivel de aplicación, ¿por qué no hago todo mi procesamiento a nivel de aplicación en lugar de usar un HTTPModule? –

11

Si estás escribiendo un HttpModule normal, básico en una aplicación administrada que desea aplicar a las solicitudes de ASP.NET a través de las páginas o manipuladores, sólo hay para asegurarse de que está usando un evento en el ciclo de vida después de la creación de la sesión. PreRequestHandlerExecute en lugar de Begin_Request suele ser donde voy. mdb lo tiene correcto en su edición.

El fragmento de código más largo originalmente enumerado como respuesta a la pregunta funciona, pero es más complicado y más amplio que la pregunta inicial. Manejará el caso cuando el contenido provenga de algo que no tenga un controlador ASP.net disponible donde pueda implementar la interfaz IRequiresSessionState, lo que activará el mecanismo de sesión para que esté disponible. (Como un archivo gif estático en el disco). Básicamente se trata de establecer un manejador ficticio que luego implementa esa interfaz para que la sesión esté disponible.

Si solo desea la sesión para su código, simplemente elija el evento adecuado para manejar en su módulo.

12

Se puede acceder al HttpContext.Current.Session en un IHttpModule en el controlador PreRequestHandlerExecute.

PreRequestHandlerExecute: "Ocurre justo antes de que ASP.NET comience a ejecutar un controlador de eventos (por ejemplo, una página o un servicio web XML)." Esto significa que antes de que se sirva una página 'aspx', este evento se ejecuta. El 'estado de la sesión' está disponible para que pueda dejarse de lado.

Ejemplo:

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

Intenté esto, y usted obtiene la Sesión de hecho. Pero parece que el RequestHeader no está completamente allí, especialmente el HeaderContentType –

0

Inténtelo: en declarar MyHttpModule clase:

private HttpApplication contextapp; 

continuación:

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

Y así, en otro método (el evento) en el mismo clase:

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"); 
    } 
} 
Cuestiones relacionadas