ASP.NET session redirect without postback - c#

I have a single page application in ASP.NET c#. All informations in the application are getting loaded using AJAX calls. There's no POSTBACK at all. However, every time I click on a different menu item that loads data from Web Services it checks if user has a valid session. Since there's no postback and when session expires users still see the main page and when they click on a menu item the data will not load since session expired (but users don't know that).
I do know how to redirect to login page when session expires if there's a postback, but how can I achieve the same result without a postback?

The only thing that comes to mind here is to use an AJAX call to a webservice which will check if the session is active, and then act accordingly. Something along these lines (untested):
ASHX handler:
<%# WebHandler Language="C#" Class="CheckSessionAlive" %>
using System;
using System.Linq;
using System.Web;
using System.Web.SessionState;
using System.Web.Script.Serialization;
public class CheckSessionAlive : IHttpHandler, IRequiresSessionState {
public void ProcessRequest (HttpContext cx) {
cx.Response.ContentType = "text/json";
cx.Response.Write(new JavaScriptSerializer().Serialize(new
{
Result = cx.Session["SomeRandomValue"] != null ? 1 : -1
}));
}
public bool IsReusable {
get {
return false;
}
}
}
Javascript (JQuery) call:
function CheckSessionAlive() {
$.ajax({
url: "CheckSessionAlive.ashx",
type: "GET",
success: function (data) {
if (data.Result == 1)
setTimeout(CheckSessionAlive, 5000); // 5 seconds
else
window.location.href = "http://www.google.com";
}
});
}
$(document).ready(function () {
CheckSessionAlive();
});
I hope it's useful :).

How does the user logs in the first place? If they login from a different page, you have to redirect them to the page to login. If you do it within your one page application, web service calls needs to return a flag indicating session status. If session expired, your ajax call should trigger login view. Hope it helps.

I was able to resolve this issue. Here's my approach.
In pageload of default.aspx I get the session time from web.config file.
protected void Page_Load(object sender, EventArgs e)
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
if (!this.IsPostBack)
{
Session["Reset"] = true;
Configuration config = WebConfigurationManager.OpenWebConfiguration("~/Web.Config");
SessionStateSection section = (SessionStateSection)config.GetSection("system.web/sessionState");
int timeout = (int)section.Timeout.TotalMinutes * 1000 * 60;
ClientScript.RegisterStartupScript(this.GetType(), "SessionAlert", "SessionExpireAlert(" + timeout + ");", true);
}
}
And then using JavaScript function I do a countdown and show a warning message when it hits 60 seconds.
<script type="text/javascript">
function SessionExpireAlert(timeout) {
var seconds = timeout / 1000;
document.getElementsByName("secondsIdle").innerHTML = seconds;
setInterval(function () {
seconds--;
document.getElementById("secondsIdle").innerHTML = seconds;
}, 1000);
setTimeout(function () {
//Show Popup before 20 seconds of timeout.
toastr.info('You will be logged out in: <span id="secondsIdle">' '</span> seconds.<br/>Click here to stay logged in.', "Warning",
{ timeOut: 0, 'position-class': 'toast-tontainer',onclick: renewSessionState}
}, timeout - 20 * 1000);
setTimeout(function () {
window.location = "logout.aspx";
}, timeout);
};
</script>
function renewSessionState() {
$.ajax({
url: "/Handlers/Ping.ashx",
method: 'POST'
});
}
Note* Ping.ashx is just an empty handler.

Related

Increase Session timeout after user wants to extend a Session?

After user login I am set user data ,Session timeout0,SessionTimeoutDate in Session.Just like that where SeessionHelper.LoggedUser has user Data.
SessionHelper.LoggedInUser.SessionTimeout = HttpContext.Session.Timeout;
SessionHelper.LoggedInUser.SessionWillExpireOn = DateTime.Now.AddMinutes(HttpContext.Session.Timeout);
this session value i get in html page for interval.
And in js i am setting interval to continuously checking current date is greater than SessionWillExpireOn if is there means session timeout i open up pop up which has two button Extend session and terminate session. If user click extend button Then I called Ajax to increase session timeout just like this.
$(document).ready(function () {
myVar = setInterval(checkSession, 500);
$('#btnExtend').click(function () {
$.ajax({
type: "GET",
url: "/User/SetSession",
cache: false,
async: true
}).success(function (data) {
console.log('1');
myVar = setInterval(checkSession, 500);
}).fail(function () {
console.log('2');
});
});
});
function checkSession() {
if (new Date(moment(new Date()).format('MM/DD/YYYY HH:mm')) > new Date(moment(SessionWillExpireOn).format('MM/DD/YYYY HH:mm'))) {
console.log('Session expried');
$('#SessionExpireModal').foundation('reveal', 'open');
clearInterval(myVar);
}
}
Extend function increase session by 2 mintues
HttpContext.Session.Timeout = 2;
SessionHelper.LoggedInUser.SessionTimeout = HttpContext.Session.Timeout;
SessionHelper.LoggedInUser.SessionWillExpireOn = DateTime.Now.AddMinutes(HttpContext.Session.Timeout);
It will increase session timeout after that success of setSession method after that i started interval to check sessionTimeout.
My main question is it is Best way to increase sessiontimeout or it is something else that i can reduce my code. Beacause after Extend button click it will call setSession Method will increase Session value and SessionTimeOut. But in My interval function i get sessionTimeout of previous value not current updated once. How to overcome this Problem so that i get updated session timeout value in Interval Function.
Any Suggestion.

how to alive session as long as possible in asp.net 3.5

i 'm working with asp.net 3.5. i just want to session alive as long as possible (browser closed). here i just following this steps :
1) session timeout value changing to web config failed.
2) Using some external .ashx file and calling with javascript at master page like below technique:
<%# WebHandler Language="C#" Class="SessionHeartbeat" %>
using System;
using System.Web;
using System.Web.SessionState;
public class SessionHeartbeat : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
context.Session["Heartbeat"] = DateTime.Now;
}
public bool IsReusable {
get {
return false;
}
}
}
this javascript at master page :
<script type="text/javascript">
function setHeartbeat() {
setTimeout("heartbeat()", 300000); // every 5 min
}
function heartbeat() {
$.post(
"../SessionHeartbeat.ashx?Timestamp" + new Date().toString()",
null,
function(data) {
//$("#heartbeat").show().fadeOut(1000); // just a little "red flash" in the corner :)
setHeartbeat();
},
"json"
);
}
</script>
but it's not give me the result that i want it.
please help me...
------------------------------------Upadated---------------------------------------
here i modify my jquery :
<script type="text/javascript">
function setHeartbeat() {
setTimeout("heartbeat()", 300000); // every 5 min
}
function heartbeat() {
$.get(
"../SessionHeartbeat.ashx",
null,
function(data) {
beatHeart(2); // just a little "red flash" in the corner :)
setHeartbeat();
},
"json"
);
}
// 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);
}
</script>
----------------------------------Upadted----------------------------------------
Here is a working example for the OP.
Web.config - Set small timeout for testing
<sessionState mode="InProc" timeout="2"/>
Javscript (in page for this example)
<script type="text/javascript">
var interval = null;
(function() {
// keep me alive
interval = setInterval(function (){
$.get('keepalive.ashx', function (d) {
$('#response').append(d + '<br/>');
});
}, 30000);
})();
// If we want to stop the interval....
function Stop() {
clearInterval(interval);
}
</script>
This prints the sessionId in an element called response so we can see the session id.
keepalive.ashx Generic handler (needs System.Web.SessionState)
public class keepalive : IHttpHandler, IRequiresSessionState {
public void ProcessRequest (HttpContext context) {
if (context.User.Identity.IsAuthenticated)
{
// authenticated sessions
context.Response.ContentType = "text/plain";
context.Response.Write("Auth:" + context.Session.SessionID);
}
else
{
// guest
context.Response.ContentType = "text/plain";
context.Response.Write("NoAuth:" + context.Session.SessionID);
}
}
Note: One thing that wasn't asked is is your keepalive supposed to be run on an authenticated session? If so, I wonder if there is also a cookie expiration issue?

How to handle session in asp.net mvc

How can I do this in Asp.Net MVC?
Activity Timer : When user navigates on the page (means doing something that calls ActionResult) the timer will reset.
When the user doesn't do any activity in more than 15 minutes, he will be prompted and be asked "Are you still there?" (Yes/LogOut), if he click yes, then activity timer will go back to zero, and starting counting again.
This activity timer must be unique per user and must be destroy upon logging out.
PLEASE PLEASE! Be PATIENT TO ME! I don't know how to this.
I had posted this question but I didn't get any answer that solves this problem. So I plan to do it from the start, and I need some help/guide to do it properly.
Any reference links or tutorials will be much appreciated!
I would handle this on the client. Create an object to encapsulate the functionality.
Something like:
var UserInactivityMonitor = UserInactivityMonitor || {};
UserInactivityMonitor = (function (module) {
var inactivityIndex;
var promptIndex;
var timer;
module.startInactivityMonitor = function () {
module.timerTick();
};
module.timerTick = function () {
inactivityIndex--;
if (inactivityIndex === 0) {
module.fireInactivityAlert();
}
if (inactivityIndex === promptIndex) {
module.fireIdlePrompt();
}
timer = setTimeout(module.timerTick, 1000);
};
module.fireIdlePrompt = function () {
var response = confirm('are you stil there?');
if (response === true) {
module.resetInactivityIndex();
}
};
module.resetInactivityIndex = function () {
inactivityIndex = 15;
promptIndex = 5;
};
module.fireInactivityAlert = function () {
alert('Inactivity alert!');
};
module.initialize = function () {
module.resetInactivityIndex();
module.startInactivityMonitor();
};
return module;
})(UserInactivityMonitor || {});
Set inactivityIndex to the number of seconds that will pass before the inactivity event fires. Set promptIndex to the number of seconds remaining when the user will be prompted if they are still there. The code above sets the inactivity timeout to 15 seconds and a idle prompt will be invoked at the 5 second remaining mark.
On page load start the inactivity timer:
$(function () {
UserInactivityMonitor.initialize();
});
On any AJAX request, reset the counter:
$("#fooButton").on('click', function () {
$.ajax(
{
url: $("#buttonClickPostUrl").val(),
data: {
someData: 'data'
},
type: 'POST',
complete: function () {
UserInactivityMonitor.resetInactivityIndex();
}
});
});
If the server is maintaining session state then you will want to make a request back to the server to kill the session and optionally direct the browser to the appropriate page for the event. You would do this in the fireInactivityAlert() function.

session timeout on ajax call

I know this is duplicate but I could not get reliable solution(for asp.net web).
I just want to redirect to the login page if session expires.
I have tried following:
1. using jquery status code
$.ajax({
type: "POST",
url: "stream.asmx/SomeMethod",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
//success msg
},
error: function (request, status, error) {
if (status = 403) {
location.href = 'login.aspx';
}
}
});
Problem: this returns same status code(403) for other errors too, which I only expect for session timeout.
2. Sending json message whether session expired
code behind:
if (!object.Equals(HttpContext.Current.Session["User"], null))
{
Id = int.Parse(HttpContext.Current.Session["User"].ToString());
}
else
{
result = from row in dtscrab.AsEnumerable()
select new
{
redirectUrl = "login.aspx",
isRedirect = true
};
}
on $.ajax success:
success: function (msg) {
if (msg.d[0].isRedirect) {
window.location.href = msg.d[0].redirectUrl;
}
else {
//load containt
}
}
Problem: It's somehow desn't invoke ajax success line if session expires(it does return correct json). And even this is not a proper way if I have many number of ajax request in the page(should be handled globally).
However, I saw this post which is really good soltion but it's for mvc using AuthorizeAttribute: handling-session-timeout-in-ajax-calls
So, Is there I can use same concept used in mvc using AuthorizeAttribute in asp.net web api? If not, how I can troubleshoot those issue which I'm facing (any of above two mentioned)?
A 403 status code is going to cause jQuery to call the failure method. Keep the same code behind from your second try, but move the redirect handler to the failure method instead of the success method. In the success method, treat it as you normally would.
Problem:
I had same problem in my Razor MVC Application throwing exceptions while ajax calls made when session timed out.
The way I have managed to get this issue sorted is by monitoring each ajax requests by using a simple light weight Action Method (RAZOR MVC) returning a bool variable whether the Request is Authenticated or not. Please find the code below..
Layout/Master Page / Script file:
<script>
var AuthenticationUrl = '/Home/GetRequestAuthentication';
var RedirectUrl = '/Account/Logon';
function SetAuthenticationURL(url) {
AuthenticationUrl = url;
}
function RedirectToLoginPage() {
window.location = RedirectUrl;
}
$(document).ajaxStart(function () {
$.ajax({
url: AuthenticationUrl,
type: "GET",
success: function (result) {
if (result == false) {
alert("Your Session has expired.Please wait while redirecting you to login page.");
setTimeout('RedirectToLoginPage()', 1000);
}
},
error: function (data) { debugger; }
});
})
Then in Home Controller/Server side you need a method to verify the request and return the boolean variable..
public ActionResult GetAuthentication ( )
{
return Json(Request.IsAuthenticated, JsonRequestBehavior.AllowGet);
}
This will validate each ajax request and if the session got expired for any ajax request, it will alert the user with a message and redirect the user to the login page.
I would also suggest not to use standard Alert to Alert. User some Tool tip kind of formatted div Alerts. Standard JS Alerts might force the user to click OK before redirection.
Hope it helps.. :)
Thanks,
Riyaz
Finally, I ended up following.
public class IsAuthorizedAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
var sessions = filterContext.HttpContext.Session;
if (sessions["User"] != null)
{
return;
}
else
{
filterContext.Result = new JsonResult
{
Data = new
{
status = "401"
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
//xhr status code 401 to redirect
filterContext.HttpContext.Response.StatusCode = 401;
return;
}
}
var session = filterContext.HttpContext.Session;
if (session["User"] != null)
return;
//Redirect to login page.
var redirectTarget = new RouteValueDictionary { { "action", "LogOn" }, { "controller", "Account" } };
filterContext.Result = new RedirectToRouteResult(redirectTarget);
}
}
Handling client side
<script type="text/javascript">
$(document).ajaxComplete(
function (event, xhr, settings) {
if (xhr.status == 401) {
window.location.href = "/Account/LogOn";
}
});
</script>
you can set session time out expire warning some thing like ....
<script type="text/javascript">
//get a hold of the timers
var iddleTimeoutWarning = null;
var iddleTimeout = null;
//this function will automatically be called by ASP.NET AJAX when page is loaded and partial postbacks complete
function pageLoad() {
//clear out any old timers from previous postbacks
if (iddleTimeoutWarning != null)
clearTimeout(iddleTimeoutWarning);
if (iddleTimeout != null)
clearTimeout(iddleTimeout);
//read time from web.config
var millisecTimeOutWarning = <%= int.Parse(System.Configuration.ConfigurationManager.AppSettings["SessionTimeoutWarning"]) * 60 * 1000 %>;
var millisecTimeOut = <%= int.Parse(System.Configuration.ConfigurationManager.AppSettings["SessionTimeout"]) * 60 * 1000 %>;
//set a timeout to display warning if user has been inactive
iddleTimeoutWarning = setTimeout("DisplayIddleWarning()", millisecTimeOutWarning);
iddleTimeout = setTimeout("TimeoutPage()", millisecTimeOut);
}
function DisplayIddleWarning() {
alert("Your session is about to expire due to inactivity.");
}
function TimeoutPage() {
//refresh page for this sample, we could redirect to another page that has code to clear out session variables
location.reload();
}
4xx are HTTP error status codes and would cause jquery to execute the onFailure callback.
Also, beware of using 3xx for redirects when you want to process the payload. Internet Explorer, in my experience, just does a redirect (without looking at the payload) when a 3xx status code is returned.
I'd say, throw a 403 and handle the situation. To the client 403 implies the resource access is forbidden. There can be multiple reasons, which is OK I guess.
For those using a ScriptManager, you can easily check for ajax request and then redirect with the following code:
private void AjaxRedirect(string url)
{
Response.StatusCode = 200;
Response.RedirectLocation = url;
Response.Write("<html></html>");
Response.End();
}
Then check for request type and redirect accordingly (using routes here):
if (ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
{
var redirectUrl = RouteTable.Routes.GetVirtualPath(null, "Default", null).VirtualPath;
AjaxRedirect(redirectUrl);
}
else
{
Response.RedirectToRoute("Default");
}
The "Default" route is a route defined in the routes collection:
routes.MapPageRouteWithName("Default", "", "~/default.aspx");
If you prefer, instead of using ScriptManager for ajax request check, you can use:
if (Request.Headers["X-Requested-With"] == "XMLHttpRequest") {
code here...
}

Keeping ASP.NET Session Open / Alive

Which is the easiest and most unobstrusive way to keep an ASP.NET session alive as long as the user has the browser window open? Is it timed AJAX calls? I want to prevent the following: sometimes users keep their window open for a long time, then enter stuff, and on submit nothing works anymore because the server side session expired. I don't want to increase the timeout value for more than 10 min on the server as I want closed sessions (by closing the browser window) to time out fast.
Suggestions, code samples?
I use JQuery to perform a simple AJAX call to a dummy HTTP Handler that does nothing but keeping my Session alive:
function setHeartbeat() {
setTimeout("heartbeat()", 5*60*1000); // 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 can be as simple as:
public class SessionHeartbeatHttpHandler : IHttpHandler, IRequiresSessionState
{
public bool IsReusable { get { return false; } }
public void ProcessRequest(HttpContext context)
{
context.Session["Heartbeat"] = DateTime.Now;
}
}
The key is to add IRequiresSessionState, otherwise Session won't be available (= null). The handler can of course also return a JSON serialized object if some data should be returned to the calling JavaScript.
Made available through web.config:
<httpHandlers>
<add verb="GET,HEAD" path="SessionHeartbeat.ashx" validate="false" type="SessionHeartbeatHttpHandler"/>
</httpHandlers>
added from balexandre on August 14th, 2012
I liked so much of this example, that I want to improve with the HTML/CSS and the beat part
change this
//$("#heartbeat").show().fadeOut(1000); // just a little "red flash" in the corner :)
into
beatHeart(2); // just a little "red flash" in the corner :)
and add
// 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 and CSS
<div class="heartbeat">♥</div>
/* HEARBEAT */
.heartbeat {
position: absolute;
display: none;
margin: 5px;
color: red;
right: 0;
top: 0;
}
here is a live example for only the beating part: http://jsbin.com/ibagob/1/
If you are using ASP.NET MVC – you do not need an additional HTTP handler and some modifications of the web.config file. All you need – just to add some simple action in a Home/Common controller:
[HttpPost]
public JsonResult KeepSessionAlive() {
return new JsonResult {Data = "Success"};
}
, write a piece of JavaScript code like this one (I have put it in one of site’s JavaScript file):
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()", 5*60*1000);
}
function KeepSessionAlive() {
if (keepSessionAlive && keepSessionAliveUrl != null) {
$.ajax({
type: "POST",
url: keepSessionAliveUrl,
success: function () { keepSessionAlive = false; }
});
}
CheckToKeepSessionAlive();
}
, and initialize this functionality by calling a JavaScript function:
SetupSessionUpdater('/Home/KeepSessionAlive');
Please note! I have implemented this functionality only for authorized users (there is no reason to keep session state for guests in most cases) and decision to keep session state active is not only based on – is browser open or not, but authorized user must do some activity on the site (move a mouse or type some key).
Whenever you make a request to the server the session timeout resets. So you can just make an ajax call to an empty HTTP handler on the server, but make sure the handler's cache is disabled, otherwise the browser will cache your handler and won't make a new request.
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 - There is no need for the overhead of storing variables in the session. Just preforming a request to the server is enough.
Do you really need to keep the session (do you have data in it?) or is it enough to fake this by reinstantiating the session when a request comes in? If the first, use the method above. If the second, try something like using the Session_End event handler.
If you have Forms Authentication, then you get something in the Global.asax.cs like
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);
...
}
And you set the ticket lifetime much longer than the session lifetime. If you're not authenticating, or using a different authentication method, there are similar tricks. Microsoft TFS web interface and SharePoint seem to use these - the give away is that if you click a link on a stale page, you get authentication prompts in the popup window, but if you just use a command, it works.
you can just write this code in you java script file thats it.
$(document).ready(function () {
var delay = (20-1)*60*1000;
window.setInterval(function () {
var url = 'put the url of some Dummy page';
$.get(url);
}, delay);
});
The (20-1)*60*1000 is refresh time, it will refresh the session timeout. Refresh timeout is calculated as default time out of iis = 20 minutes, means 20 × 60000 = 1200000 milliseconds - 60000 millisecond (One minutes before session expires ) is 1140000.
[Late to the party...]
Another way to do this without the overhead of an Ajax call or WebService handler is to load a special ASPX page after a given amount of time (i.e., prior to the session state time-out, which is typically 20 minutes):
// Client-side JavaScript
function pingServer() {
// Force the loading of a keep-alive ASPX page
var img = new Image(1, 1);
img.src = '/KeepAlive.aspx';
}
The KeepAlive.aspx page is simply an empty page which does nothing but touch/refresh the Session state:
// KeepAlive.aspx.cs
public partial class KeepSessionAlive: System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Refresh the current user session
Session["refreshTime"] = DateTime.UtcNow;
}
}
This works by creating an img (image) element and forcing the browser to load its contents from the KeepAlive.aspx page. Loading that page causes the server to touch (update) the Session object, extending the session's expiration sliding time window (typically by another 20 minutes). The actual web page contents are discarded by the browser.
An alternative, and perhaps cleaner, way to do this is to create a new iframe element and load the KeepAlive.aspx page into it. The iframe element is hidden, such as by making it a child element of a hidden div element somewhere on the page.
Activity on the page itself can be detected by intercepting mouse and keyboard actions for the entire page body:
// Called when activity is detected
function activityDetected(evt) {
...
}
// Watch for mouse or keyboard activity
function watchForActivity() {
var opts = { passive: true };
document.body.addEventListener('mousemove', activityDetected, opts);
document.body.addEventListener('keydown', activityDetected, opts);
}
I cannot take credit for this idea; see:
https://www.codeproject.com/Articles/227382/Alert-Session-Time-out-in-ASP-Net.
Here is a alternative solution that should survive if the client pc goes into sleep mode.
If you have a huge amount of logged in users then use this cautiously as this could eat a lot of server memory.
After you login (i do this in the LoggedIn event of the login control)
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)
I spent a few days trying to figure out how to prolong a users session in WebForms via a popup dialog giving the user the option to renew the session or to allow it to expire. The #1 thing that you need to know is that you don't need any of this fancy 'HttpContext' stuff going on in some of the other answers. All you need is jQuery's $.post(); method. For example, while debugging I used:
$.post("http://localhost:5562/Members/Location/Default.aspx");
and on your live site you would use something like:
$.post("http://mysite/Members/Location/Default.aspx");
It's as easy as that. Furthermore, if you'd like to prompt the user with the option to renew their session do something similar to the following:
<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>
Don't forget to add the Dialog to your 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>
In regards to veggerby's solution, if you are trying to implement it on a VB app, be careful trying to run the supplied code through a translator. The following will work:
Imports System.Web
Imports System.Web.Services
Imports System.Web.SessionState
Public Class SessionHeartbeatHttpHandler
Implements IHttpHandler
Implements IRequiresSessionState
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Session("Heartbeat") = DateTime.Now
End Sub
End Class
Also, instead of calling like heartbeat() function like:
setTimeout("heartbeat()", 300000);
Instead, call it like:
setInterval(function () { heartbeat(); }, 300000);
Number one, setTimeout only fires once whereas setInterval will fire repeatedly. Number two, calling heartbeat() like a string didn't work for me, whereas calling it like an actual function did.
And I can absolutely 100% confirm that this solution will overcome GoDaddy's ridiculous decision to force a 5 minute apppool session in Plesk!
Here JQuery plugin version of Maryan solution with handle optimization. Only with JQuery 1.7+!
(function ($) {
$.fn.heartbeat = function (options) {
var settings = $.extend({
// These are the defaults.
events: 'mousemove keydown'
, url: '/Home/KeepSessionAlive'
, every: 5*60*1000
}, 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)
and how it does import in your *.cshtml
$('body').heartbeat(); // Simple
$('body').heartbeat({url:'#Url.Action("Home", "heartbeat")'}); // different url
$('body').heartbeat({every:6*60*1000}); // different timeout

Categories

Resources