Showing posts with label Session expiration on client side. Show all posts
Showing posts with label Session expiration on client side. Show all posts

Monday, November 14, 2011

How to handle Session Timeout in Jquery calls in MVC

In my last project, we used Jquery Ajax calls severly for almost all postbacks in the application. Then we had this situration - Jquery Ajax calls throwing 503 Server error (Object reference null) all the places on Server Session Expiration. Here how we handled this particular problem.

Step 1 - First came up a extension method which will check if server session expires and the code is as follows:


public static bool IsSessionExpired(this HttpSessionStateBase session)
{
if (session == null || !session.IsNewSession)
{
return false;
}

// If it says it is a new session, but an existing cookie exists, then it must have timed out
string sessionCookie = HttpContext.Current.Request.Headers["Cookie"];
return sessionCookie != null && sessionCookie.Contains("ASP.NET_SessionId");
}


Step 2 - Design an Attribute that will call the above routine on every action executed in any controller of the Application. You can apply this attribute on your BaseController at the class level. The code is as follows:


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class SessionExpireAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
HttpContext ctx = HttpContext.Current;

// check if session is supported
if (ctx.Session != null)
{
if (filterContext.HttpContext.Session.IsSessionExpired())
{
var viewData = filterContext.Controller.ViewData;
viewData.Model = username;
filterContext.HttpContext.Response.StatusCode = 504;
filterContext.Result = new ViewResult { ViewName = "SessionTimeout", ViewData = viewData };
}
}
}

}


Step 3 - Equip your Ajax Calls with Error Handler that will check for Error Status Code = 504 and redirect the user to SessionTimeout page.


//$.Ajax Get/Post Calls

$("#NewTemplate").live("click", function () {
if (confirmNavigation($(this))) {
$("#selectedTemplateId").val(0);
$.ajax({
type: "GET",
url: Urls.NewTemplate,
async: false,
cache: false,
success: function (cb) {
if (!cb) {
alert("Unable to load the screen");
}
else {
uiChanges = true;
$("#divTemplate").html(cb);
}
},
error: function (xhr, textStatus, errorThrown) {
redirectOnSessionTimeout(xhr.status);
}

});
}
});

//$.load Ajax Calls

function loadAuditTableGrid(name) {
$("#auditTableGrid").load(
Urls.AuditTable,
{ auditTableName: name },
function (response, status, xhr) { redirectOnSessionTimeout(xhr.status); });
}

//$.getJSON way
reqJSON(Urls.CheckForActiveState, { id: selectedId},
function (result) {
if (!result.success)
$("#Message").show();
else
$("#Message").hide();

}, function (xhr, textStatus, errorThrown) {
redirectOnSessionTimeout(xhr.status);
});

function reqJSON(url, params, success, error) {
var CallParams = {};
CallParams.type = params.Method || "POST";
CallParams.url = url;
CallParams.processData = true;
CallParams.data = params;
CallParams.dataType = "json";
CallParams.success = success;
if (error) {
CallParams.error = error;
}
$.ajax(CallParams);
}

function redirectOnSessionTimeout(status) {
if (status == "504") {
location.href = Urls.SessionTimeout;
}
}