ASP.NET-Sitzung offen / aktiv halten

Welches ist die einfachste und unaufdringlichste Art, eine ASP.NET-Sitzung am Leben zu erhalten, solange der Benutzer das Browserfenster geöffnet hat? Werden AJAX-Anrufe zeitgesteuert? Ich möchte Folgendes verhindern: manchmal halten Benutzer ihr Fenster für eine lange Zeit offen, dann geben sie Zeug ein, und beim Abschicken funktioniert nichts mehr, weil die serverseitige Sitzung abgelaufen ist. Ich möchte den Zeitüberschreitungswert für mehr als 10 Minuten auf dem Server nicht erhöhen, da ich geschlossene Sitzungen (durch Schließen des Browserfensters) für ein schnelles Timeout wünschen möchte.

Vorschläge, Codebeispiele?

   

Ich benutze JQuery, um einen einfachen AJAX-Aufruf an einen Dummy-HTTP-Handler durchzuführen, der nur meine Sitzung am Laufen hält:

function setHeartbeat() { setTimeout("heartbeat()", 300000); // every 5 min } function heartbeat() { $.get( "/SessionHeartbeat.ashx", null, function(data) { //$("#heartbeat").show().fadeOut(1000); // just a little "red flash" in the corner :) setHeartbeat(); }, "json" ); } 

Session-Handler kann so einfach sein wie:

 public class SessionHeartbeatHttpHandler : IHttpHandler, IRequiresSessionState { public bool IsReusable { get { return false; } } public void ProcessRequest(HttpContext context) { context.Session["Heartbeat"] = DateTime.Now; } } 

Der Schlüssel ist das Hinzufügen von IRequiresSessionState, andernfalls ist Session nicht verfügbar (= null). Der Handler kann natürlich auch ein serialisiertes JSON-Objekt zurückgeben, wenn einige Daten an das aufrufende JavaScript zurückgegeben werden sollen.

Verfügbar über web.config:

    

hinzugefügt von balexandre am 14. August 2012

Ich mochte so viel von diesem Beispiel, dass ich mit dem HTML / CSS und dem Beat-Teil verbessern möchte

ändere das

 //$("#heartbeat").show().fadeOut(1000); // just a little "red flash" in the corner :) 

in

 beatHeart(2); // just a little "red flash" in the corner :) 

und hinzufügen

 // beat the heart // 'times' (int): nr of times to beat function beatHeart(times) { var interval = setInterval(function () { $(".heartbeat").fadeIn(500, function () { $(".heartbeat").fadeOut(500); }); }, 1000); // beat every second // after n times, let's clear the interval (adding 100ms of safe gap) setTimeout(function () { clearInterval(interval); }, (1000 * times) + 100); } 

HTML und CSS

 
/* HEARBEAT */ .heartbeat { position: absolute; display: none; margin: 5px; color: red; right: 0; top: 0; }

Hier ist ein Live-Beispiel für nur den schlagenden Teil: http://jsbin.com/ibagob/1/

Wenn Sie ASP.NET MVC verwenden, benötigen Sie keinen zusätzlichen HTTP-Handler und einige Änderungen der Datei web.config. Alles, was Sie brauchen – nur um eine einfache Aktion in einem Home / Common-Controller hinzuzufügen:

 [HttpPost] public JsonResult KeepSessionAlive() { return new JsonResult {Data = "Success"}; } 

, schreibe ein Stück JavaScript-Code wie dieses (ich habe es in eine JavaScript-Datei der Site eingefügt):

 var keepSessionAlive = false; var keepSessionAliveUrl = null; function SetupSessionUpdater(actionUrl) { keepSessionAliveUrl = actionUrl; var container = $("#body"); container.mousemove(function () { keepSessionAlive = true; }); container.keydown(function () { keepSessionAlive = true; }); CheckToKeepSessionAlive(); } function CheckToKeepSessionAlive() { setTimeout("KeepSessionAlive()", 300000); } function KeepSessionAlive() { if (keepSessionAlive && keepSessionAliveUrl != null) { $.ajax({ type: "POST", url: keepSessionAliveUrl, success: function () { keepSessionAlive = false; } }); } CheckToKeepSessionAlive(); } 

und initialisieren Sie diese functionalität durch Aufruf einer JavaScript-function:

 SetupSessionUpdater('/Home/KeepSessionAlive'); 

Bitte beachten Sie! Ich habe diese functionalität nur für autorisierte Benutzer implementiert (es gibt in den meisten Fällen keinen Grund, den Sitzungsstatus für Gäste beizubehalten) und die Entscheidung, den Sitzungsstatus aktiv zu halten, basiert nicht nur auf – ist der Browser geöffnet oder nicht, sondern der autorisierte Benutzer muss etwas tun auf der Website (bewegen Sie eine Maus oder geben Sie einen Schlüssel ein).

Immer wenn Sie eine Anfrage an den Server stellen, wird das Sitzungszeitlimit zurückgesetzt. Sie können also einfach einen Ajax-Aufruf an einen leeren HTTP-Handler auf dem Server machen, aber sicherstellen, dass der Cache des Handlers deaktiviert ist, da der Browser sonst Ihren Handler zwischenspeichert und keine neue Anfrage macht.

KeepSessionAlive.ashx.cs

 public class KeepSessionAlive : IHttpHandler, IRequiresSessionState { public void ProcessRequest(HttpContext context) { context.Response.Cache.SetCacheability(HttpCacheability.NoCache); context.Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1)); context.Response.Cache.SetNoStore(); context.Response.Cache.SetNoServerCaching(); } } 

.JS:

 window.onload = function () { setInterval("KeepSessionAlive()", 60000) } function KeepSessionAlive() { url = "/KeepSessionAlive.ashx?"; var xmlHttp = new XMLHttpRequest(); xmlHttp.open("GET", url, true); xmlHttp.send(); } 

@veggerby – Der Aufwand für das Speichern von Variablen in der Sitzung entfällt. Es genügt, eine Anfrage an den Server zu richten.

Müssen Sie die Sitzung wirklich behalten (haben Sie Daten darin?) Oder ist es genug, um dies zu fälschen, indem Sie die Sitzung neu installieren, wenn eine Anfrage eingeht? Verwenden Sie als Erstes die obige Methode. Wenn das zweite Problem auftritt, versuchen Sie etwas wie den Session_End Event-Handler.

Wenn Sie eine Formularauthentifizierung haben, erhalten Sie etwas in der Datei Global.asax.cs

 FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(formsCookie.Value); if (ticket.Expired) { Request.Cookies.Remove(FormsAuthentication.FormsCookieName); FormsAuthentication.SignOut(); ... } else { ... // renew ticket if old ticket = FormsAuthentication.RenewTicketIfOld(ticket); ... } 

Und Sie legen die Lebensdauer des Tickets viel länger als die Lebensdauer der Sitzung fest. Wenn Sie sich nicht authentifizieren oder eine andere Authentifizierungsmethode verwenden, gibt es ähnliche Tricks. Die Microsoft TFS-Webschnittstelle und SharePoint scheinen diese zu verwenden – das Verschenken ist, dass Sie, wenn Sie auf eine veraltete Seite klicken, Authentifizierungsaufforderungen im Popup-Fenster erhalten, aber wenn Sie nur einen Befehl verwenden, funktioniert es.

Sie können diesen Code einfach in Ihre Java Script-Datei schreiben.

 $(document).ready(function () { window.setInterval(function () { var url = 'put the url of some Dummy page'; $.get(url); },1140000); }); 

Die 1140000 ist die Aktualisierungszeit, sie aktualisiert das Sitzungszeitlimit. Das Refresh-Timeout wird als Standardzeit aus iis = 20 Minuten berechnet, bedeutet 20 × 60000 = 1200000 Millisekunden – 60000 Millisekunden (eine Minute vor Ablauf der Sitzung) ist 1140000.

Hier ist eine alternative Lösung, die überleben sollte, wenn der Client-PC in den Ruhezustand wechselt.

Wenn Sie eine große Menge an angemeldeten Benutzern haben, dann verwenden Sie dies vorsichtig, da dies viel Serverspeicher essen könnte.

Nach dem Login (ich mache das im LoggedIn-Event des Login-Controls)

 Dim loggedOutAfterInactivity As Integer = 999 'Minutes 'Keep the session alive as long as the authentication cookie. Session.Timeout = loggedOutAfterInactivity 'Get the authenticationTicket, decrypt and change timeout and create a new one. Dim formsAuthenticationTicketCookie As HttpCookie = _ Response.Cookies(FormsAuthentication.FormsCookieName) Dim ticket As FormsAuthenticationTicket = _ FormsAuthentication.Decrypt(formsAuthenticationTicketCookie.Value) Dim newTicket As New FormsAuthenticationTicket( ticket.Version, ticket.Name, ticket.IssueDate, ticket.IssueDate.AddMinutes(loggedOutAfterInactivity), ticket.IsPersistent, ticket.UserData) formsAuthenticationTicketCookie.Value = FormsAuthentication.Encrypt(newTicket) 

Ich habe ein paar Tage damit verbracht, herauszufinden, wie man eine Benutzersitzung in WebForms über einen Popup-Dialog verlängert, der dem Benutzer die Option gibt, die Sitzung zu erneuern oder zu erlauben, dass sie abläuft. Die # 1 Sache, die Sie wissen müssen, ist, dass Sie nichts von diesem ausgefallenen ‘HttpContext’ Zeugs in einigen der anderen Antworten brauchen. Alles, was Sie brauchen, ist jQuerys $ .post (); Methode. Zum Beispiel habe ich beim Debuggen folgendes benutzt:

 $.post("http://localhost:5562/Members/Location/Default.aspx"); 

und auf deiner Live-Seite würdest du etwas verwenden wie:

 $.post("http://mysite/Members/Location/Default.aspx"); 

So einfach ist das. Wenn Sie den Benutzer mit der Option zum Erneuern der Sitzung auffordern möchten, gehen Sie wie folgt vor:

   

Vergessen Sie nicht, den Dialog zu Ihrem HTML hinzuzufügen:

   

Hier JQuery Plugin Version von Maryan Lösung mit Griffoptimierung. Nur mit JQuery 1.7+!

 (function ($) { $.fn.heartbeat = function (options) { var settings = $.extend({ // These are the defaults. events: 'mousemove keydown' , url: '/Home/KeepSessionAlive' , every: 300000 }, options); var keepSessionAlive = false , $container = $(this) , handler = function () { keepSessionAlive = true; $container.off(settings.events, handler) }, reset = function () { keepSessionAlive = false; $container.on(settings.events, handler); setTimeout(sessionAlive, settings.every); }, sessionAlive = function () { keepSessionAlive && $.ajax({ type: "POST" , url: settings.url ,success: reset }); }; reset(); return this; } })(jQuery) 

und wie es in Ihren * .cshtml importiert

 $('body').heartbeat(); // Simple $('body').heartbeat({url:'@Url.Action("Home", "heartbeat")'}); // different url $('body').heartbeat({every:400000}); // different timeout