2

I have a problem with Ajax requests and redirects. I tried creating a custom authorize attribute as follows:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyAuthorizeAttribute : AuthorizeAttribute

public override void OnAuthorization(AuthorizationContext filterContext)        
{
    base.OnAuthorization(filterContext);            
    if (filterContext.Result == null || (filterContext.Result.GetType() != typeof(HttpUnauthorizedResult) 
        || !filterContext.HttpContext.Request.IsAjaxRequest()))                
        return;                

    var redirectToUrl = "/login?returnUrl=" + filterContext.HttpContext.Request.UrlReferrer.PathAndQuery;   
    filterContext.Result = (filterContext.HttpContext.Request.ContentType == "application/json"  
        ? (ActionResult)                  
        new JsonResult                  
        { 
            Data = new { RedirectTo = redirectToUrl },                      
            ContentEncoding = System.Text.Encoding.UTF8,                      
            JsonRequestBehavior = JsonRequestBehavior.DenyGet                  
        }                
        : new ContentResult                
        {
            Content = redirectToUrl,                    
            ContentEncoding = System.Text.Encoding.UTF8,                    
            ContentType = "text/html"                
        });                 

    //Important: Cannot set 401 as asp.net intercepts and returns login page            
    //so instead set 530 User access denied                       
    filterContext.HttpContext.Response.StatusCode = 530; //User Access Denied            
    filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;                    
}    
} 

But the isAjaxRequest() is always false in my application. Even when I am calling the action from a jquery .ajax() call.

EDIT: Including the ajax calls as suggested. Some of my ajax calls are made by the jqGrid component. The datatype is set to JSON and type is POST. The controllers have the HTTPPost decoration. Some of them are direct jquery ajax calls like so:

$("#clientList").change(function () {
    var client = $("#clientList").val();
    $.ajax({
        url: "myurl",
        data: { 'client': client },
        cache: false,
        traditional: true,
        type: 'POST',
        success: function (data) {
            <do something here>
        }
    });
});
Emre Erkan
  • 8,433
  • 3
  • 48
  • 53
SimpleUser
  • 1,341
  • 2
  • 16
  • 36
  • There have been a number of problems like this here: http://stackoverflow.com/questions/14629304/httpcontext-current-request-isajaxrequest-error-in-mvc-4 and http://stackoverflow.com/questions/5164540/why-doesnt-request-isajaxrequest-work-in-asp-net-mvc-3 do either of those get you an answer? – Faust Nov 08 '13 at 18:11
  • @faust, I've had a look at almost all similar questions on SO, but none of them helped. Hence the new post. – SimpleUser Nov 08 '13 at 18:14
  • I got the above code when searching through google at this link https://gist.github.com/beckelmw/1487699. I've tried several similar approaches in my authorize attribute, but I still can't get it to work right. Using MVC3, jquery1.6.4, have the correct script calls to jquery. I'm calling the controller actions using jquery's .ajax() method. – SimpleUser Nov 08 '13 at 18:17
  • Have you tried changing the jquery `.ajax()` call's options, such as type (post vs get)? Posting your jquery might help someone come up with an answer. – Faust Nov 08 '13 at 19:10
  • isAjaxRequest checks for `X-Requested-Wit`h in the request header (http://stackoverflow.com/questions/4523827/asp-net-mvc-what-does-isajaxrequest-actually-mean) This post: http://stackoverflow.com/questions/11440918/jquery-get-ajax-response-headers tells you how to check the headers sent by jquery `ajax()`. I would examine those headers. – Faust Nov 08 '13 at 19:16
  • @Faust, the header is present in the header according to Fiddler. Some of my calls are through the jqGrid component, and the datatype is set to json and type to POST. The controller has the corresponding httpost decorations. Others call jquery ajax like this $("#clientList").change(function () { var client = $("#clientList").val() $.ajax({ url: "myurl", data: { 'client': client }, cache: false, traditional: true, type: 'POST', success: function (data) { } }); }); – SimpleUser Nov 09 '13 at 06:53
  • Well, that's a stumper, isn't it. At this point I would consider re-writing the `IsAjaxRequest` functionality. Here's a post where someone's done that because of problems with the JQuery Form plugin: http://stackoverflow.com/questions/1681563/detecting-isajaxrequest-with-asp-net-mvc-and-jquery-form-plugin-file-upload . You don't have to plop the answerer's code into your project as is, of course, just put the core logic (checking `filterContext.HttpContext.Request.Headers["X-Requested-With"]`) where you would like it to reside. – Faust Nov 09 '13 at 07:33

0 Answers0