Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asp.net mvc [handleerror] [authorize] with JsonResult?

What is an elegant way to leverage the existing [HandleError] and [Authorize] attributes when dealing with XHR calls from javascript?

So, say for example a method GetJson which returns a JsonResult.

When an error occurs, the [HandleError] method will send back a ViewResult which will be retrived in the callback function in javascript.

I'd then have to place custom code everywhere in javascript to handle and redirect any crashes, etc.

What I'd like to do, is have the [HandleError] attribute return a JsonResult if the original action was planning to do that. This might be wishful thinking on my part.

Similarly, if an unauthorized Json request comes in, instead of returning a new HttpUnauthorizedResult I'd like to return a JsonResult that allows my client side code to handle things in a common manner.

Am I barking up the wrong tree here? Maybe there's an even nicer way that MVC can handle this which I'm unaware of?

How are other people handling this scenario?

Thanks.

PS: I realize I can create my own [HandleJsonError] and [AuthorizeJson] attributes which return JsonResults instead of ViewResults, but then I'd have to go around and place these on any method that returns Json, and worry about Filter order etc. It sure would be nice if I could use reflection or something to have the same attribute act differently depending on the signature of the original method.

like image 689
Scott Klarenbach Avatar asked Oct 22 '09 20:10

Scott Klarenbach


1 Answers

You don't. Right now, they don't help with JSON. However:

I realize I can create my own [HandleJsonError] and [AuthorizeJson] attributes which return JsonResults instead of ViewResults, but then I'd have to go around and place these on any method that returns Json, and worry about Filter order etc.

What we did is to subtype the existing attributes, and make them work conditionally:

public sealed class AjaxAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
        if (filterContext.Result == null)
        {
            return;
        }
        else if (filterContext.Result.GetType() == typeof(HttpUnauthorizedResult) 
            && filterContext.HttpContext.Request.IsAjaxRequest())
        {
            filterContext.Result = new ContentResult();
            filterContext.HttpContext.Response.StatusCode = 403;
        }
    }
}

Now the JS code can look for 403 (because ASP.NET eats 401 and returns the error page) and the same attribute works for Ajax and non-Ajax. So no filter order issues.

like image 98
Craig Stuntz Avatar answered Nov 19 '22 17:11

Craig Stuntz