Mantener la sesión de ASP.NET abierta / viva

¿Cuál es la forma más fácil y menos obscena de mantener viva una sesión de ASP.NET mientras el usuario tenga abierta la ventana del navegador? ¿Se trata de llamadas AJAX temporizadas? Quiero evitar lo siguiente: a veces los usuarios mantienen su ventana abierta durante mucho tiempo, luego ingresan cosas, y al enviar nada, nada funciona porque la sesión del lado del servidor expiró. No deseo boost el valor de tiempo de espera durante más de 10 minutos en el servidor, ya que quiero que las sesiones cerradas (al cerrar la ventana del navegador) excedan el tiempo de espera.

Sugerencias, muestras de código?

Uso JQuery para realizar una simple llamada AJAX a un manejador HTTP ficticio que no hace más que mantener viva mi sesión:

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

El controlador de sesión puede ser tan simple como:

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

La clave es agregar IRequiresSessionState, de lo contrario la sesión no estará disponible (= null). El controlador también puede devolver un objeto serializado JSON si algunos datos se deben devolver al JavaScript que realiza la llamada.

Disponible a través de web.config:

    

agregado de balexandre el 14 de agosto de 2012

Me gustó mucho este ejemplo, que quiero mejorar con el HTML / CSS y la parte de compás

cambia esto

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

dentro

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

y añadir

 // 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 y CSS

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

aquí hay un ejemplo en vivo solo para la parte de la paliza: http://jsbin.com/ibagob/1/

Si está utilizando ASP.NET MVC, no necesita un controlador HTTP adicional y algunas modificaciones del archivo web.config. Todo lo que necesita, solo para agregar alguna acción simple en un controlador de Inicio / Común:

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

, escriba un fragmento de código JavaScript como este (lo puse en uno de los archivos JavaScript del sitio):

 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(); } 

e inicialice esta funcionalidad llamando a una función de JavaScript:

 SetupSessionUpdater('/Home/KeepSessionAlive'); 

¡Tenga en cuenta! Implementé esta funcionalidad solo para usuarios autorizados (no hay motivo para mantener el estado de la sesión para invitados en la mayoría de los casos) y la decisión de mantener activo el estado de sesión no solo se basa en – está abierto o no el navegador, pero el usuario autorizado debe realizar alguna actividad en el sitio (mueva un mouse o escriba alguna clave).

Cada vez que realiza una solicitud al servidor, se restablece el tiempo de espera de la sesión. Por lo tanto, puede hacer una llamada ajax a un manejador HTTP vacío en el servidor, pero asegúrese de que la memoria caché del manejador esté desactivada, de lo contrario, el navegador guardará en caché su controlador y no realizará una nueva solicitud.

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 – No hay necesidad de la sobrecarga de almacenar variables en la sesión. Solo es necesario realizar una solicitud al servidor.

¿Realmente necesita mantener la sesión (¿tiene datos?) O ¿es suficiente para simular esto al volver a iniciar la sesión cuando se recibe una solicitud? Si es el primero, usa el método de arriba. Si es el segundo, intente con algo como usar el controlador de eventos Session_End.

Si tiene Autenticación de formularios, entonces obtendrá algo en Global.asax.cs como

 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); ... } 

Y configura el tiempo de vida del ticket mucho más tiempo que la duración de la sesión. Si no está autenticando, o usa un método de autenticación diferente, hay trucos similares. La interfaz web Microsoft TFS y SharePoint parecen usar estos: el regalo es que si haces clic en un enlace en una página obsoleta, obtienes indicaciones de autenticación en la ventana emergente, pero si solo usas un comando, funciona.

puedes escribir este código en tu archivo de script java, eso es todo.

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

El 1140000 es tiempo de actualización, actualizará el tiempo de espera de la sesión. El tiempo de espera de actualización se calcula como tiempo predeterminado fuera de iis = 20 minutos, significa 20 × 60000 = 1200000 milisegundos – 60000 milisegundos (Un minuto antes de que la sesión caduque) es 1140000.

Aquí hay una solución alternativa que debería sobrevivir si la PC del cliente entra en modo de suspensión.

Si tienes una gran cantidad de usuarios conectados, utiliza esto con cuidado, ya que podría consumir mucha memoria del servidor.

Después de iniciar sesión (esto lo hago en el evento LoggedIn del control de inicio de sesión)

 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) 

Pasé unos días tratando de averiguar cómo prolongar la sesión de un usuario en WebForms a través de un diálogo emergente que le da al usuario la opción de renovar la sesión o permitir que caduque. Lo # 1 que debes saber es que no necesitas que nada de este elegante material de “HttpContext” continúe en algunas de las otras respuestas. Todo lo que necesitas es jQuery’s $ .post (); método. Por ejemplo, durante la depuración utilicé:

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

y en tu sitio en vivo usarías algo como:

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

Es tan fácil como eso. Además, si desea solicitar al usuario la opción de renovar su sesión, haga algo similar a lo siguiente:

   

No olvide agregar el cuadro de diálogo a su html:

   

Aquí, la versión del complemento JQuery de la solución Maryan con optimización del manipulador. ¡Solo con 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) 

y cómo se importa en su * .cshtml

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