web-dev-qa-db-fra.com

Puis-je accéder à l'état de la session à partir d'un HTTPModule?

Je pourrais vraiment faire avec la mise à jour des variables de session d'un utilisateur depuis mon HTTPModule, mais d'après ce que je peux voir, ce n'est pas possible.

UPDATE: Mon code est en cours d'exécution dans le gestionnaire d'événements OnBeginRequest ().

MISE À JOUR: Suite aux conseils reçus jusqu'à présent, j'ai essayé d'ajouter ceci à la routine Init () dans mon HTTPModule:

AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute

Mais dans ma routine OnPreRequestHandlerExecute, l'état de la session est toujours indisponible!

Merci et excuses s'il me manque quelque chose!

84
Chris Roberts

Trouvé ceci sur le forums 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,
// 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; }
      }
   }
}
80
Jim Harte

HttpContext.Current.Session devrait simplement fonctionner, en supposant que votre module HTTP ne gère aucun événement de pipeline qui se produit avant que l'état de la session ne soit initialisé ...

EDIT, après clarification dans les commentaires: lors de la gestion de l’événement BeginRequest , l’objet Session sera toujours null/Nothing, car il n’a pas encore été initialisé par le runtime ASP.NET. Pour contourner ce problème, déplacez votre code de gestion vers un événement qui se produit après PostAcquireRequestState - J'aime PreRequestHandlerExecute pour moi-même, car tout le travail de bas niveau est pratiquement effectué à ce stade, mais vous devez toujours préempter tout traitement normal.

39
mdb

L'accès au HttpContext.Current.Session dans une IHttpModule peut être effectué dans le gestionnaire PreRequestHandlerExecute

PreRequestHandlerExecute : "Se produit juste avant qu'ASP.NET commence à exécuter un gestionnaire d'événements (par exemple une page ou un service Web XML)." Cela signifie qu'avant l'exécution d'une page 'aspx', cet événement est exécuté. L'état de session est disponible pour que vous puissiez vous assommer.

Exemple:

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

Si vous écrivez un HttpModule normal de base dans une application gérée que vous souhaitez appliquer aux demandes asp.net via des pages ou des gestionnaires, vous devez simplement vous assurer que vous utilisez un événement dans le cycle de vie après la création de la session. PreRequestHandlerExecute au lieu de Begin_Request est généralement l'endroit où je vais. mdb a le droit dans son édition.

L'extrait de code le plus long indiqué à l'origine comme répondant à la question fonctionne, mais est plus complexe et plus large que la question initiale. Il gérera le cas où le contenu provient de quelque chose pour lequel aucun gestionnaire ASP.net n'est disponible et où vous pouvez implémenter l'interface IRequiresSessionState, déclenchant ainsi le mécanisme de session pour le rendre disponible. (Comme un fichier gif statique sur le disque). Il s'agit essentiellement de définir un gestionnaire factice qui implémente ensuite cette interface pour rendre la session disponible.

Si vous voulez juste la session pour votre code, il vous suffit de choisir le bon événement à gérer dans votre module.

11
Rob

Essayez-le: dans la classe MyHttpModule, déclarez:

private HttpApplication contextapp;

Ensuite:

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

Et ainsi, dans une autre méthode (l'événement) dans la même classe:

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");
    }
}
0
aTest