Mantendo a session do ASP.NET aberta / viva

Qual é a maneira mais fácil e mais discreta de manter uma session ASP.NET ativa enquanto o usuário tiver a janela do navegador aberta? São chamadas AJAX cronometradas? Eu quero evitar o seguinte: às vezes, os usuários mantêm a janela aberta por um longo tempo, depois entram em material e, em não enviar nada funciona, porque a session do lado do servidor expirou. Eu não quero aumentar o valor de tempo limite por mais de 10 min no servidor, pois eu quero sessões fechadas (fechando a janela do navegador) para o tempo limite rápido.

Sugestões, exemplos de código?

Eu uso o JQuery para executar uma simples chamada AJAX para um manipulador HTTP fictício que não faz nada além de manter minha session ativa:

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

O manipulador de session pode ser tão simples quanto:

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

A chave é adicionar IRequiresSessionState, caso contrário, a Session não estará disponível (= null). O manipulador também pode retornar um object serializado JSON se alguns dados devem ser retornados para o JavaScript de chamada.

Disponibilizado através do web.config:

    

adicionado de balexandre em 14 de agosto de 2012

Gostei muito deste exemplo, que quero melhorar com o HTML / CSS e a parte da batida

mude isso

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

para dentro

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

e adicione

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

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

Aqui está um exemplo ao vivo apenas para a parte de espancamento: http://jsbin.com/ibagob/1/

Se você estiver usando o ASP.NET MVC, não será necessário um manipulador HTTP adicional e algumas modificações do arquivo web.config. Tudo que você precisa – apenas para adicionar alguma ação simples em um controlador Home / Common:

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

, escreva um pedaço de código JavaScript como este (coloquei em um dos arquivos JavaScript do site):

 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 inicialize essa funcionalidade chamando uma function JavaScript:

 SetupSessionUpdater('/Home/KeepSessionAlive'); 

Observe! Implementei essa funcionalidade apenas para usuários autorizados (não há motivo para manter o estado da session para convidados na maioria dos casos) e a decisão de manter o estado da session ativo não se baseia apenas – o navegador está aberto ou não, mas o usuário autorizado deve realizar alguma atividade no site (mova um mouse ou digite alguma chave).

Sempre que você faz uma solicitação ao servidor, o tempo limite da session é redefinido. Assim, você pode apenas fazer uma chamada de ajax para um manipulador HTTP vazio no servidor, mas certifique-se de que o cache do manipulador esteja desativado, caso contrário, o navegador armazenará em cache seu manipulador e não fará uma nova solicitação.

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 – Não há necessidade de sobrecarga de armazenamento de variables ​​na session. Apenas pré-formando um pedido para o servidor é suficiente.

Você realmente precisa manter a session (você tem dados nela?) Ou é o suficiente para falsificar isso, reinstantiando a session quando uma requisição chega? Se o primeiro, use o método acima. Se o segundo, tente algo como usar o manipulador de events Session_End.

Se você tem Autenticação de Formulários, então você obtém algo no 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); ... } 

E você define o tempo de vida do ticket muito mais do que o tempo de vida da session. Se você não estiver autenticando ou usando um método de autenticação diferente, existem truques semelhantes. A interface da Web do Microsoft TFS e o SharePoint parecem usá-los – o resultado é que, se você clicar em um link em uma página obsoleta, obterá prompts de autenticação na janela pop-up, mas se usar um comando, funcionará.

você pode simplesmente escrever esse código em seu arquivo de script java.

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

O 1140000 é tempo de atualização, ele atualizará o tempo limite da session. O tempo limite de atualização é calculado como o tempo de espera padrão fora de iis = 20 minutos, significa 20 × 60000 = 1200000 milissegundos – 60000 milissegundos (um minuto antes da session expirar) é 1140000.

Aqui está uma solução alternativa que deve sobreviver se o PC cliente entrar no modo de suspensão.

Se você tiver uma quantidade enorme de usuários logados, use-a com caucanvas, pois isso pode consumir muita memory do servidor.

Depois de fazer o login (eu faço isso no evento LoggedIn do controle de login)

 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) 

Passei alguns dias tentando descobrir como prolongar uma session de usuários no WebForms através de uma checkbox de diálogo pop-up, dando ao usuário a opção de renovar a session ou permitir que ela expirasse. A coisa # 1 que você precisa saber é que você não precisa de nenhuma dessas coisas sofisticadas do ‘HttpContext’ acontecendo em algumas das outras respostas. Tudo que você precisa é $ .post () do jQuery; método. Por exemplo, durante a debugging, usei:

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

e no seu site ao vivo você usaria algo como:

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

É tão fácil quanto isso. Além disso, se você quiser solicitar ao usuário a opção de renovar a session, faça algo semelhante ao seguinte:

   

Não esqueça de adicionar o Dialog ao seu html:

   

Aqui JQuery plugin versão da solução Maryan com otimização de identificador. Apenas com o 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) 

e como importar no seu * .cshtml

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