In one of my web application I need to popup alert when session timeout in 5 minutes. Users have option either continue to extend the session or log out immediately.
In Web.config set session timeout to 30 min:
<sessionState mode="InProc" timeout="30">
Since ASP.NET MVC do not give a way to check the remaining session timeout, I come up a solution as follow:
In Global.asax it tracks the current session last access time as a session variable. If the coming in request is not session state readonly (see below), the last access time session variable is updated with current time. Otherwise session variable's value is set with current time.
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
var context = HttpContext.Current;
if (context != null && context.Session != null && !context.Session.IsReadOnly)
{
context.Session["_LastAccessTime"] = DateTime.Now;
}
}
In my session controller, I set the session state behavior to read only. Requests to this controller neither reset session nor do it refresh my last access time session variable.
[SessionState(SessionStateBehavior.ReadOnly)]
public class SessionController : BaseController
{
[AjaxOnly]
public ActionResult GetRemainingSessionTimeout()
{
if (!Request.IsAjaxRequest())
{
return Content("Not an Ajax call.");
}
var remainingSessionTimeout = 0;
if (Session["_LastAccessTime"] != null)
{
var lastAccessTime = (DateTime) Session["_LastAccessTime"];
var timeSpan = DateTime.Now.Subtract(lastAccessTime);
remainingSessionTimeout = Session.Timeout - timeSpan.Minutes;
}
return Json(new {RemainingSessionTimeout = remainingSessionTimeout}, JsonRequestBehavior.AllowGet);
}
}
In a view, Ajax request checks the remaining session timeout silently. If less than 5 min, then popup alert:
$(document).ready(function () {
$("#remainingSessionTimeout").click(function (e) {
var url = '@Url.Action("GetRemainingSessionTimeout", "Session", new { area = "" })';
$.ajax({
type: "POST",
url: url,
data: {},
success: function (result) {
$("#timeoutLeft").html('Your session expries in ' + result.Timeout * 60 + ' seconds.');
},
error: function (result) {
$("#timeoutLeft").html('error in getting session data.');
}
});
});
});
Any drawback or flaw of this solution? Thanks.