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");
- 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) {
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 of Controller
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
{
}
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 (session.IsNewSession || Session["LoginUser"] == null)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
JsonResult result = Json("SessionTimeout", "text/html");
filterContext.Result = result;
}
else
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary {
{ "Controller", "Accounts" },
{ "Action", "Login" }
});
}
}
base.OnActionExecuting(filterContext);
}
}
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);
}
}
});
}