Prevent displaying Log In page in partial view on ajax request after session expired in ASP.NET MVC

If you are using partial views with many ajax request, there might be a situation in which user session expires and if you will try to submit form asynchronously via ajax  Log in page will be displayed in partial view(this will occur if you are using authorize attribute on the method you are calling).

Add this method to global.asax.cs file.

 // To use for ajax request when user session expired

protected void Application_EndRequest()
        {
            var context = new HttpContextWrapper(Context);
            // If we're an ajax request, and doing a 302, then we actually need to do a 401
            if (Context.Response.StatusCode == 302 && context.Request.IsAjaxRequest())
            {
                Context.Response.Clear();
                Context.Response.StatusCode = 401;
            }
        }

In main.js file or script section on your main view(cshtml file if using Razor) add this:

var  $document = $(document);

handleAjaxError = function (XMLHttpRequest, textStatus, errorThrown) {
    if (XMLHttpRequest.status == 401) {
        //refresh the page, as we are not longer authorized
        location.reload();
    }
    };
 
Since we already lost session, we want to refresh the page and user will be redirect automatically to Log in page, rather than displaying Log in page in small partial view.

    $document.ajaxComplete(function(event, XMLHttpRequest, AjaxOptions){
        handleAjaxError(XMLHttpRequest);
    }); 

http://api.jquery.com/ajaxComplete/ - More on ajax Complete method

http://stackoverflow.com/questions/3431343/asp-net-mvc-forces-an-ajax-request-be-redirected-to-the-login-page-when-the-form - Inspired by this post

Comments

  1. This worked for me... but because I don't like magic numbers I refactored it to this:

    protected void Application_EndRequest()
    {
    var context = new HttpContextWrapper(Context);

    if (Context.Response.StatusCode == (int)HttpStatusCode.Redirect && context.Request.IsAjaxRequest())
    {
    Context.Response.Clear();
    Context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
    }
    }

    Thanks!
    --SBC

    ReplyDelete
  2. Yes, using enums is of course possible in this case. I just wanted to be consistent with javascript code, plus it is good to know which http status code means as you would get response from most services as an integer.

    ReplyDelete

Post a Comment