Frage

Vor kurzem, während für eine ASP.NET-Projekt bei der Arbeit an einigen Code zu arbeiten. Wir brauchten util eine Tracking-Basismetriken auf Benutzeraktivität zu nehmen (Seite treffen usw. zählen) wir sie in Session , dann die Daten an die DB speichern über Session_End in Global.asax .

ich weg begann Hacker, der anfängliche Code hat gut funktioniert, auf jeder Seite zu laden, die DB zu aktualisieren. Ich wollte, obwohl diese DB treffen auf jede Anfrage entfernen und verlassen sich nur auf Session_End alle Daten zu speichern.

Alle Tracking-Code wird in der Tracker Klasse gekapselt, einschließlich Eigenschaften, die im Wesentlichen die Session-Variablen wickeln.

Das Problem ist, dass, wenn ich Tracker.Log() im Session_End Methode ausgeführt, die HttpContext.Current.Session im Tracker-Code wurde mit einem NullReferenceException . Nun ist dies sinnvoll, da HttpContext immer auf die bezieht Strom Anfrage und natürlich in Session_End, gibt es keine Anfrage.

Ich weiß, dass Global.asax eine Session Eigenschaft hat, die eine HttpSessionState zurückgibt, scheint tatsächlich zu funktionieren (ich landete sie in an den Tracker Injektion) ..

Aber ich bin neugierig, wie zum Teufel kann ich den gleichen Verweis auf das HttpSessionState Objekt erhalten, indem Global.asax von verwendet außerhalb von Global.asax?

Vielen Dank im Voraus Jungs, ich schätze die Eingabe. :)

War es hilfreich?

Lösung

Global.asax implementiert Httpapplication -. Das ist, was Sie sprechen, wenn Sie anrufen dieses aus it

Die MSDN-Dokumentation für Httpapplication hat Details zu wie können Sie halten es in einem Httphandler zum Beispiel, und dann Zugriff auf die verschiedenen Eigenschaften auf es.

JEDOCH

Ihre Anwendung kann mehrere Instanzen von Httpapplication erstellen parallel Anfragen zu bearbeiten, und diese Fälle wiederverwendet werden können, so einfach es irgendwie Abholung wird nicht zu garantieren, dass Sie die richtigen haben.

Auch ich würde auch eine Notiz von Vorsicht hinzufügen - wenn Ihre Anwendung abstürzt, gibt es keine Garantie, die aufgerufen werden Session_End wird, und Sie werden alle Daten in allen Sitzungen verloren haben, eindeutig nicht eine gute Sache.

Ich bin damit einverstanden, dass auf jeder Seite der Anmeldung ist wahrscheinlich keine gute Idee, aber vielleicht ein halbes Haus mit einigen asynchronen Protokollierung geschieht - Sie Details Feuer auf eine Logging-Klasse aus, dass jeder von Zeit zu Zeit protokolliert die Details, die Sie nach sind - noch wenn die App abstürzt nicht zu 100% fest, aber Sie sind weniger wahrscheinlich, alles zu verlieren.

Andere Tipps

die ursprüngliche Frage zu beantworten, besser:

Hintergrund

Jede einzelne Seite Anfrage spinnt ein neues Session Objekt und dann bläht es aus Ihrer Sitzung zu speichern. Dazu verwendet er die vom Kunden zur Verfügung gestellt Cookie oder eine speziellen Pfad construct (für Sitzungen ohne Cookies). Mit diesem Sitzungs-ID, konsultiert er die Sitzung zu speichern und deserialisiert (aus diesem Grunde alle Anbieter aber InProc sein müssen Serializable) Objekt der neue Sitzung.

Im Falle des InProc Anbieter, nur Hände Sie den Verweis in der HttpCache gespeichert durch die Sitzungs-ID eingegeben. Diese ist, warum der InProc Anbieter Sitzungszustand fällt, wenn die AppDomain zurückgeführt wird (und warum auch mehrere Web-Server nicht InProc Sitzungsstatus teilen .

Das neu erstellt und aufgeblasen Objekt wird in der Context.Items Sammlung stecken, so dass sie für die Dauer der Anforderung verfügbar sind.

Alle Änderungen an das Session Objekt vornehmen, werden dann am Ende des Antrags an den Sitzungsspeicher beharrte durch Serialisierung (oder im Fall von InProc, der HttpCache Eintrag aktualisiert wird).

Da Session_End Brände ohne aktuelle Anforderung in-fly, wird das Objekt Session versponnen Ab-Werk-nilo, ohne Informationen verfügbar. Wenn InProc Sitzungszustand verwendet wird, löst sich der Ablauf der HttpCache eine Callback-Ereignis in Ihrem Session_End Ereignis, so dass der Sitzungseintrag ist vorhanden, aber es ist immer noch eine Kopie dessen, was zuletzt in der HttpContext.Cache gespeichert. Dieser Wert wird gespeichert gegen die HttpApplication.Session Eigenschaft durch ein internes Verfahren (genannt ProcessSpecialRequest), wo es dann zur Verfügung. In allen anderen Fällen kommt es intern vom HttpContext.Current.Session Wert.

Ihre Antwort

Da die Session_End immer feuert gegen einen Null-Kontext, sollten Sie immer this.session in diesem Fall und übergeben Sie die Httpsessionstate zu Ihrem Tracing-Code Objekt nach unten. In allen anderen Bereichen, ist es völlig in Ordnung, von HttpContext.Current.Session zu holen und dann den Verfolgungscode passiert in. NICHT , lassen jedoch der Verfolgungscode für den Sitzungskontext reicht.

Meine Antwort

Verwenden Sie Session_End nicht, wenn Sie wissen, dass die Sitzung speichern Sie unterstützt Session_End verwenden, die es funktioniert , wenn es true von SetItemExpireCallback zurückgibt. Das einzige in-the-Box-Geschäft, das tut, ist der InProcSessionState Speicher. Es ist möglich, einen Session-Speicher zu schreiben, das tut aber die Frage, wer Art mehrdeutig die Session_End ist, wird verarbeitet, wenn es mehrere Server.

Ich glaube, Sie bereits Ihre eigene Frage beantwortet: in der Regel der Session-Immobilie in Global.asax und HttpContext.Current.Session gleich ist (wenn es eine aktuelle Anforderung ist). Aber im Fall eines Session-Timeout, gibt es keine aktive Anfrage und daher können Sie nicht HttpContext.Current verwenden.

Wenn Sie die Sitzung aus dem von Session_End aufgerufen zugreifen wollen, dann geben sie als Parameter. Erstellen Sie eine überladene Version der Log () -Methode, die ein Httpsessionstate als Parameter annimmt, dann rufen Tracker.Log (this.session) von der Session_End Ereignishandler.

BTW: Sie sind sich bewusst, dass Sie nicht auf der Sitzung Ende Ereignis in jedem Fall verlassen können? Es wird nur so lange arbeiten, wie Sie den Sitzungsstatus in-Prozess haben. Wenn SQL Server oder State mit dem Sitzungsstatus Räude, wird die Sitzung-End-Ereignis nicht ausgelöst.

Das Session_End Ereignis wird nur ausgelöst, wenn der sessionstate mode gesetzt in der InProc Datei Web.config. Wenn Sitzungsmodus StateServer oder SQLServer gesetzt ist, wird das Ereignis nicht ausgelöst.

Verwendung Session["SessionItemKey"] den Sitzungswert zu erhalten.

Okay, ich bin in dem gleichen Problem die Sitzungsaktivität zu verfolgen. Statt Session_End Ereignis zu verwenden, habe ich die IDisposable-Schnittstelle und destructor meine sessiontracker Klasse implementiert. Ich habe die Methode Dispose () modifiziert, um die Sitzungsaktivität an die DB zu speichern. I aufgerufen, um das Verfahren obj.Dispose (), wenn ein Benutzer die Logout Schaltfläche klickt. Wenn der Benutzer den Browser versehentlich geschlossen, dann wird GC den Destruktor aufrufen, während die Objekte Reinigung (nicht sofort, aber sicher wird es diese Methode, nach einiger Zeit nennen). Die Destruktormethode intern führen Sie die gleiche Methode Dispose () die Sitzungsaktivitäten in DB zu speichern.

-Shan

Session ist in der Datei Global.asax, während der Session_Start Veranstaltung. Vielleicht bis dahin warten, Dinge zu tun?

Beachten Sie, dass Session_End läuft, wenn die Sitzung abläuft, ohne Aktivität. Der Browser stammt nicht das Ereignis (weil es inaktiv ist), so dass die einzige Zeit, die Sie das Ereignis tatsächlich erhalten wird, wenn der InProc Anbieter verwendet. In jedem anderen Anbieter, wird dieses Ereignis nie ausgelöst.

Moral? Nicht Session_End verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top