jQuery AJAX – redirect on unathorised request

Problem

In default ASP.NET MVC setup, when you send a AJAX request to the MVC Action which returns JSON or simple type value (boolean / string) and the request is not authenticated (user has just logged out or authentication cookie has expired) your jQuery success callback will be fired with a login page HTML content as data. That happens because default AuthorizeAttribute redirects unauthenticated requests to he login page, and jQuery follows this redirect and does not provide a simple way of telling what just happened nor why the redirect was performed.

Solution

To overcome this inconvenience you can roll custom AuthorizeAttribute which will redirect standard HTML requests (caused by forms posting and browser url change) to the login change but return an error code (which can be detected on the jQuery script side) for AJAX request.

public class AJAXAwareAuthorizeAttribute : AuthorizeAttribute
    {
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
                filterContext.Result = new HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
            else
                base.HandleUnauthorizedRequest(filterContext);
        }
    }

 

Then you can add a global AJAX handler to check for the 403 (Forbidden) code on each AJAX request and redirect/show error/do anything else when this code is returned from the controller.

$(document).ajaxError(function (event, xhr, settings, error) {
    //when there is an AJAX request and the user is not authenticated -> redirect to the login page
    if (xhr.status == 403) { // 403 - Forbidden
        window.location = '/login';
    }
});
 Now your success callback will not fire for unauthenticated requests and the error callback will be triggered instead

jQuery – how to get the validation framework to work with hidden fields

Problem

jQuery validation does not validate hidden fields by default, even when appropriate attributes (data-val, data-val-required etc.) are applied.

Solution

You can change that by overwriting jQuery validation defaults. There is a ignore field which is set to :hidden which causes all hidden elements to be skipped when validation happens.

If you want only specific hidden fields to get validated you can do something like this:

$.validator.setDefaults({
        ignore: ":hidden:not([data-validate-hidden])"
    });

 

This will cause all hidden fields to be ignored by validation framework unless they have data-validate-hidden attribute.