保持ASP.NET会话打开/活着

只要用户打开浏览器窗口,保持ASP.NET会话活动的最简单,最简单的方法是什么? 定时AJAX调用? 我想要防止以下情况:有时用户长时间保持窗口打开,然后input东西,并提交什么工作了,因为服务器端会话过期。 我不想在服务器上增加10分钟以上的超时值,因为我想要closures会话(通过closures浏览器窗口)来快速超时。

build议,代码示例?

我使用JQuery来执行一个简单的AJAX调用一个虚拟的HTTP处理程序,除了保持我的会话不活动:

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

会话处理程序可以像下面这样简单:

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

关键是添加IRequiresSessionState,否则Session将不可用(= null)。 处理程序当然也可以返回一个JSON序列化对象,如果一些数据应该返回到调用JavaScript。

通过web.config提供:

 <httpHandlers> <add verb="GET,HEAD" path="SessionHeartbeat.ashx" validate="false" type="SessionHeartbeatHttpHandler"/> </httpHandlers> 

2012年8月14日从Balexandre 添加

我非常喜欢这个例子,我想用HTML / CSS和节拍部分来改进

改变这一点

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

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

并添加

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

 <div class="heartbeat">&hearts;</div> /* HEARBEAT */ .heartbeat { position: absolute; display: none; margin: 5px; color: red; right: 0; top: 0; } 

这里仅仅是一个跳动部分的实例 : http : //jsbin.com/ibagob/1/

如果您使用的是ASP.NET MVC,则不需要额外的HTTP处理程序以及对web.config文件的一些修改。 您只需要在Home / Common控制器中添加一些简单的操作:

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

,写下这样一段JavaScript代码(我把它放在一个网站的JavaScript文件中):

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

,并通过调用JavaScript函数来初始化这个function:

 SetupSessionUpdater('/Home/KeepSessionAlive'); 

请注意! 我只为授权用户实现了这个function(在大多数情况下,没有任何理由保持会话状态),并且保持会话状态活跃的决定不仅基于 – 浏览器是否打开,而是授权用户必须做一些活动在网站上(移动鼠标或键入一些键)。

无论何时向服务器发出请求,会话超时都会重置。 所以你可以只对服务器上的一个空的HTTP处理器进行ajax调用,但要确保处理器的caching被禁用,否则浏览器将caching你的处理程序,不会发出新的请求。

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 – 不需要在会话中存储variables的开销。 只是预先形成一个请求到服务器就足够了。

你真的需要保持这个会话吗(你有数据吗?)还是足够的虚假的通过重新实例会话时,请求进来? 如果第一个,使用上面的方法。 如果第二个,尝试使用Session_End事件处理程序。

如果你有表单身份validation,那么你可以在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); ... } 

而且,您设置的票据使用期限比会话使用期限长得多。 如果你不authentication,或使用不同的authentication方法,也有类似的技巧。 微软的TFS Web界面和SharePoint似乎使用这些 – 放弃的是,如果你点击一个旧的页面上的链接,你会在popup窗口中的身份validation提示,但如果你只是使用一个命令,它的工作原理。

你可以把这个代码写在你的java脚本文件中就行了。

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

刷新时间为1140000,会刷新会话超时。 刷新超时计算为默认时间超出iis = 20分钟,意味着20×60000 = 1200000毫秒-60000毫秒(会话到期前一分钟)是1140000。

如果客户端电脑进入睡眠模式,这是另一种解决scheme。

如果您有大量的login用户,请谨慎使用,因为这可能会消耗大量的服务器内存。

login后(我在login控制的LoggedIn事件中这样做)

 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) 

我花了几天的时间试图找出如何通过popup对话框让用户select更新会话或允许它过期来延长WebForms中的用户会话。 你需要知道的#1事情是,你不需要任何这种奇特的“HttpContext”的东西在一些其他的答案。 所有你需要的是jQuery的$ .post(); 方法。 例如,我在debugging时使用:

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

在你的网站上你会使用像这样的东西:

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

就这么简单 此外,如果您想要提醒用户select更新会话,请执行以下操作:

  <script type="text/javascript"> $(function () { var t = 9; var prolongBool = false; var originURL = document.location.origin; var expireTime = <%= FormsAuthentication.Timeout.TotalMinutes %>; // Dialog Counter var dialogCounter = function() { setTimeout( function() { $('#tickVar').text(t); t--; if(t <= 0 && prolongBool == false) { var originURL = document.location.origin; window.location.replace(originURL + "/timeout.aspx"); return; } else if(t <= 0) { return; } dialogCounter(); }, 1000); } var refreshDialogTimer = function() { setTimeout(function() { $('#timeoutDialog').dialog('open'); }, (expireTime * 1000 * 60 - (10 * 1000)) ); }; refreshDialogTimer(); $('#timeoutDialog').dialog({ title: "Session Expiring!", autoOpen: false, height: 170, width: 350, modal: true, buttons: { 'Yes': function () { prolongBool = true; $.post("http://localhost:5562/Members/Location/Default.aspx"); refreshDialogTimer(); $(this).dialog("close"); }, Cancel: function () { var originURL = document.location.origin; window.location.replace(originURL + "/timeout.aspx"); } }, open: function() { prolongBool = false; $('#tickVar').text(10); t = 9; dialogCounter(); } }); // end timeoutDialog }); //End page load </script> 

不要忘记将对话框添加到您的HTML:

  <div id="timeoutDialog" class='modal'> <form> <fieldset> <label for="timeoutDialog">Your session will expire in</label> <label for="timeoutDialog" id="tickVar">10</label> <label for="timeoutDialog">seconds, would you like to renew your session?</label> </fieldset> </form> </div> 

这里的JQuery插件版本的Maryan解决scheme具有句柄优化function。 只有使用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) 

以及它如何在* .cshtml中导入

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