Kann ich über ein HTTP-Modul auf den Sitzungsstatus zugreifen?

85

Ich könnte wirklich die Sitzungsvariablen eines Benutzers aus meinem HTTPModule heraus aktualisieren, aber soweit ich sehen kann, ist dies nicht möglich.

UPDATE: Mein Code wird derzeit im OnBeginRequest ()Ereignishandler ausgeführt.

UPDATE: Nach den bisher erhaltenen Ratschlägen habe ich versucht, dies der Init ()Routine in meinem HTTPModule hinzuzufügen:

AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute

Aber in meiner OnPreRequestHandlerExecuteRoutine ist der Sitzungsstatus immer noch nicht verfügbar!

Danke und Entschuldigung, wenn mir etwas fehlt!

Chris Roberts
quelle

Antworten:

82

Fand dies in den ASP.NET-Foren :

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; }
      }
   }
}
Jim Harte
quelle
8
MS sollte dies beheben! ... wenn ich ein Modul als Implementierung des IRequiresSessionState markiere, sollte ich nicht durch einen Reifen springen müssen, um es zu bekommen ... (sexy Code in der Tat)
BigBlondeViking
6
Schöner Code. Ich dachte, ich würde das brauchen, aber es stellt sich nicht heraus. Dieser Code lädt die Sitzung für jedes Bild und jede andere nicht seitenbezogene Ressource, die den Server durchläuft. In meinem Fall überprüfe ich einfach, ob die Sitzung im PostAcquireRequestState-Ereignis null ist, und kehre zurück, wenn dies der Fall ist.
Abtin Forouzandeh
7
Dieser Code ist nützlich, wenn die angeforderte Ressource den Sitzungsstatus nicht verarbeitet. Fügen Sie für Standard-ASPX-Seiten einfach Ihren Code hinzu, der auf die Sitzung im PostAcquireRequestState-Ereignishandler zugreift. Der Sitzungsstatus ist in keinem BeginRequest-Ereignishandler verfügbar, da der Sitzungsstatus noch nicht erfasst wurde.
JCallico
3
In meinem Fall funktioniert es nicht. Ich habe "Sitzungsstatus ist in diesem Kontext nicht verfügbar." wenn eine Anforderung vorliegt, die versucht, auf eine statische Datei zuzugreifen. Irgendeine Hilfe ?
Maxisam
3
Damit dies für statische Dateien funktioniert, muss ich zusätzlich das Sitzungsmodul (in der web.config) neu registrieren, indem ich preCondition = "manageHandler" (<remove name = "Session" /> <add name = "entferne. Sitzung "type =" System.Web.SessionState.SessionStateModule "/>)
nlips
39

HttpContext.Current.Session sollte einfach funktionieren , vorausgesetzt, Ihr HTTP-Modul verarbeitet keine Pipeline-Ereignisse , die vor der Initialisierung des Sitzungsstatus auftreten ...

BEARBEITEN, nach Klarstellung in Kommentaren: Bei der Behandlung des BeginRequest-Ereignisses ist das Session-Objekt tatsächlich immer noch null / Nothing, da es noch nicht von der ASP.NET-Laufzeit initialisiert wurde. Um dies zu umgehen , verschieben Sie Ihren Bearbeitungscode in ein Ereignis, das nach PostAcquireRequestState auftritt. Ich mag PreRequestHandlerExecute selbst dafür, da alle Arbeiten auf niedriger Ebene in dieser Phase so gut wie erledigt sind, aber Sie dennoch jede normale Verarbeitung verhindern.

mdb
quelle
Leider ist dies im HTTPModule nicht verfügbar - "Objektreferenz nicht auf eine Instanz eines Objekts festgelegt."
Chris Roberts
Ich verarbeite 'OnBeginRequest'?
Chris Roberts
Danke für das Update. Wenn ich es in einem Ereignis auf Anwendungsebene behandle, warum mache ich dann nicht einfach meine gesamte Verarbeitung auf Anwendungsebene, anstatt ein HTTP-Modul zu verwenden?
Chris Roberts
1
PostAcquireRequeststate ist kein Ereignis auf Anwendungsebene: Wenn die HTTP-Anforderung beispielsweise von einem Webdienst-Handler verarbeitet wird, wird sie weiterhin in Ihrem HTTP-Modul angezeigt, jedoch nicht in Global.asax ...
mdb
Das scheint bei mir nicht zuverlässig zu funktionieren. Der folgende Code verursacht häufig die Ausnahme "Sitzungsstatus ist in diesem Kontext nicht verfügbar". Tatsächlich stürzt der VS-Debugger ziemlich spektakulär ab. context.PreRequestHandlerExecute + = (Absender, Argumente) => Console.Write (((HttpApplication) Absender) .Session ["Test"];
cbp
15

Der Zugriff auf das HttpContext.Current.Sessionin a IHttpModulekann im PreRequestHandlerExecuteHandler erfolgen.

PreRequestHandlerExecute : "Tritt kurz vor dem Ausführen eines Ereignishandlers durch ASP.NET auf (z. B. eine Seite oder ein XML-Webdienst)." Dies bedeutet, dass dieses Ereignis ausgeführt wird, bevor eine Aspx-Seite bereitgestellt wird. Der 'Sitzungsstatus' ist verfügbar, damit Sie sich selbst ausschalten können.

Beispiel:

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();
        }
...
}
Bert Persyn
quelle
Ich habe es versucht, und Sie bekommen die Sitzung in der Tat. Aber es scheint, dass der RequestHeader nicht vollständig vorhanden ist, insbesondere der HeaderContentType
Matthias Müller
12

Wenn Sie ein normales, einfaches HttpModule in einer verwalteten Anwendung schreiben, die Sie über Seiten oder Handler auf asp.net-Anforderungen anwenden möchten, müssen Sie nur sicherstellen, dass Sie nach der Sitzungserstellung ein Ereignis im Lebenszyklus verwenden. PreRequestHandlerExecute anstelle von Begin_Request ist normalerweise der Ort, an den ich gehe. mdb hat es richtig in seiner edit.

Das längere Code-Snippet, das ursprünglich als Antwort auf die Frage aufgeführt war, funktioniert, ist jedoch kompliziert und umfassender als die ursprüngliche Frage. Der Fall wird behandelt, wenn der Inhalt von etwas stammt, für das kein ASP.net-Handler verfügbar ist. Dort können Sie die IRequiresSessionState-Schnittstelle implementieren und so den Sitzungsmechanismus auslösen, um ihn verfügbar zu machen. (Wie eine statische GIF-Datei auf der Festplatte). Grundsätzlich wird ein Dummy-Handler festgelegt, der diese Schnittstelle nur implementiert, um die Sitzung verfügbar zu machen.

Wenn Sie nur die Sitzung für Ihren Code wünschen, wählen Sie einfach das richtige Ereignis für Ihr Modul aus.

rauben
quelle
0

Probieren Sie es aus: In der Klasse MyHttpModule deklarieren Sie:

private HttpApplication contextapp;

Dann:

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

Und so in einer anderen Methode (dem Ereignis) in derselben Klasse:

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");
    }
}
ein Test
quelle