Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 3 / Jquery AJAX / Session Expires / C# - Handling session timeout durng ajax call

I have an ajax call to MVC which returns a partialview. This is all fine until the session ends or the cookie expires. When I make the ajax call it displays the content inside a div that was meant to be for the partialview. How can I detect that my session has expired during the ajax call and redirect properly to a full screen/page

like image 451
Arcadian Avatar asked May 14 '12 20:05

Arcadian


People also ask

How check session expired in MVC?

In web applications, session holds the information of current logged-in users. So, if the session expires in 20 minutes, then it is redirected to login page. In that case, we need to check if session exists (not null) in every action/ every controller which requires authentication. We have to two methods to check.

Does Ajax call reset session timeout?

yes, it does. it doesn't matter whether you actually use the Session or not. However, if you're using only ajax calls, you might run into some problems.


2 Answers

I would recommend encapsulating all your requests into a wrapper element:

public class JsonResponse<T>
{
    public JsonResponse()
    {
    }

    public JsonResponse(T Data)
    {
        this.Data = Data;
    }

    public T Data { get; set; }
    public bool IsValid { get; set; }
    public string RedirectTo { get; set; }
}

What model you want to send to your client is in Data.

To get the RedirectTo populated, I use a GlobalAuthorize attribute in the Global.Asax and added a handle for HandleUnauthorizedRequests.

public sealed class GlobalAuthorize : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest
      (AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            filterContext.Result = new JsonResult
            {
                Data = new JsonResponse<bool>
                       {
                           IsValid = false,
                           //RedirectTo = FormsAuthentication.LoginUrl
                           RedirectTo = "/"
                       },
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    } 

Additionally, I've encapsulated all my Ajax requests into a single function which checks for the RedirectTo.

function global_getJsonResult(Controller, View, data, successCallback, completeCallback, methodType)
{
    if (IsString(Controller)
        && IsString(View)
        && !IsUndefinedOrNull(data))
    {
        var ajaxData;
        var ajaxType;

        if (typeof (data) == "string")
        {
            ajaxData = data;
            ajaxType = "application/x-www-form-urlencoded"
        }
        else
        {
            ajaxData = JSON.stringify(data);
            ajaxType = "application/json; charset=utf-8";
        }
        var method = 'POST';

        if (!IsUndefinedOrNull(methodType)) 
        {
            method = methodType;
        }

        var jqXHR = $.ajax({
            url: '/' + Controller + '/' + View,
            data: ajaxData,
            type: method,
            contentType: ajaxType,
            success: function(jsonResult)
            {
                if (!IsUndefinedOrNull(jsonResult)
                    && jsonResult.hasOwnProperty("RedirectTo")
                    && !IsUndefinedOrNull(jsonResult.RedirectTo)
                    && jsonResult.RedirectTo.length > 0)
                {
                    $.fn.notify('error', 'Login Expired', 'You have been inactive for a prolonged period of time, and have been logged out of the system.');
                    window.setTimeout(function() { window.location = jsonResult.RedirectTo }, 5000);
                }
                else if (IsFunction(successCallback))
                {
                    successCallback(jsonResult, Controller + '/' + View);
                }
            },
            error: function(jqXHR, textStatus, errorThrown)
            {
                if (errorThrown != 'abort')
                {
                    $.fn.notify('error', 'AJAX Connection Error', textStatus + ': ' + errorThrown);
                }

            },
            complete: function(jqXHR, textStatus)
            {
                if (IsFunction(completeCallback))
                {
                    completeCallback(jqXHR, textStatus, Controller + '/' + View);
                }
            }
        });

        return jqXHR;
    }
}
like image 123
Erik Philips Avatar answered Nov 08 '22 12:11

Erik Philips


You could create a timer on the client with javascript that will show a dialog to the user when the session has timed out. You would just set the timer's value to whatever your session time out. Then on ajax request, it will reset the count down as well.

var g_sessionTimer = null;
function uiSessionInit() {
    id = "uiTimeout";
    timeout = 3600000 * 24; // 1 day timeout
    uiSessionSchedulePrompt(id, timeout);
    $('body').ajaxStart(function () {
        // reset timer on ajax request
        uiSessionSchedulePrompt(id, timeout);
    });
}
function uiSessionSchedulePrompt(id, timeout) {
    if (g_sessionTimer)
        clearTimeout(g_sessionTimer);
    g_sessionTimer = setTimeout(function () { uiSessionExpiring(id); }, timeout);
}
function uiSessionExpiring(id) {
    // create a dialog div and use this to show to the user
    var dialog = $('<div id="uiTimeout"></div>').text("Your session with has timed out. Please login again.");
    $('body').append(dialog);
    $('#uiTimeout').dialog({ 
           autoOpen: true, 
           modal: true, 
           title: 'Expired Session', 
           buttons: { 
                "OK": function(){
                    $(this).dialog('close'); 
                }
           },
           close: uiSessionDialogClose
     });
}

function uiSessionDialogClose(){
    // take user to sign in location
    location = 'http://www.mypage.com'; 
}
like image 34
Gabe Avatar answered Nov 08 '22 10:11

Gabe