Session Handling in ASP.NET MVC 5 for Synchronous/Asynchronous Requests






3.56/5 (10 votes)
Session handling for asynchronous requests made from jquery
Introduction
Basic use of session in MVC web applications is as follows:
- Check user is logged in or not
- To hold authorization information of user logged in
- To hold temporary other data
- Check session Timeout on user action for each controller
Background
Problem Statement
Using asynchronous (Ajax) request - It is a very common situation to use jquery Ajax or unobtrusive Ajax API of MVC to make asynchronous request in MVC. Both jquery Ajax and unobtrusive Ajax are very powerful to handle asynchronous mechanism. But in most situations, we prefer to use jquery Ajax to have fine tuned control over the application. And now suppose we want to check the session timeout for each asynchronous call in our application. We are using JSON to grab a data on form and send it with asynchronous request. So we dropped in situation where:
- Normal redirect won’t work well.
Example:RedirectToAction("LoginView", "LoginController"); // won't work well with Ajax calls
- We need to check session timeout in action method. A repetitive code in each action method hence reduced code reusability and maintainability.
Example:if (session.IsNewSession || Session["LoginUser"] == null) { //redirection logic }
Using the Code
Solution
We can use base controller class or take advantage of action filters of MVC.
- Using base controller class and overriding
OnActionExecuting
method ofController
class:public class MyBaseController : Controller { protected override void OnActionExecuting(ActionExecutingContext filterContext) { HttpSessionStateBase session = filterContext.HttpContext.Session; if (session.IsNewSession || Session["LoginUser"] == null) { filterContext.Result = Json("Session Timeout", "text/html"); } } }
And inheriting base class as:
public class MyController : BaseController { //action methods… }
Limitation of this approach is that it covers up each action method.
- Using action filter attribute class of MVC 5. So we can fine tune each controller action as required.
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class SessionTimeoutFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpSessionStateBase session = filterContext.HttpContext.Session;
// If the browser session or authentication session has expired...
if (session.IsNewSession || Session["LoginUser"] == null)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
// For AJAX requests, return result as a simple string,
// and inform calling JavaScript code that a user should be redirected.
JsonResult result = Json("SessionTimeout", "text/html");
filterContext.Result = result;
}
else
{
// For round-trip requests,
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary {
{ "Controller", "Accounts" },
{ "Action", "Login" }
});
}
}
base.OnActionExecuting(filterContext);
}
//other methods...
}
Jquery code at client side is as follows:
$.ajax({
type: "POST",
url: "controller/action",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify(data),
async: true,
complete: function (xhr, status) {
if (xhr.responseJSON == CONST_SESSIONTIMEOUT) {
RedirectToLogin(true);
return false;
}
if (status == 'error' || !xhr.responseText) {
alert(xhr.statusText);
}
}
});
}