ASP.NET MVC determine remaining session timeout using SessionState
Asked Answered
D

0

6

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.

Daddylonglegs answered 12/2, 2015 at 15:0 Comment(6)
InProc is a big flaw. Trying to have any sort of consistency of session length using in proc sessions is basically impossible.Jaye
Can i get rid of the inconsistency issue by switching to session state server?Daddylonglegs
Yes, because then the session is persisted. The problem with in proc is that it's stored in volatile memory. If the app pool recycles, the server restarts, etc. everything goes away.Jaye
Other than the InProc session, does the solution have any other concerns?Daddylonglegs
Are you using Forms Authentication (or any authentication that uses it) for authentication, or have you rolled your own based on Session State? Do note that Forms Authentication (the normal way of logging on) uses a different cookie and different timeout than Session State.Lacee
I use Federate authentication. <modules runAllManagedModulesForAllRequests="true"> <add name="SsoAuthentication" type="..." /><add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule.../><add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule..." /></modules>Daddylonglegs

© 2022 - 2024 — McMap. All rights reserved.