views:

487

answers:

4

I have a custom exception filter that I'm calling by virtue of adding a [CustomExceptionFilter] attribute to my class. It works as I'd like it to, however if the action method is returning a partial view (through an ajax request), the exception (which is basically a redirect to a not authorized page), is loading up the partial view with that page. Is there a way I can force it to reload the 'parent' url?

Here is the code for the custom exception filter

public class CustomExceptionFilter : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        if (filterContext.Exception.GetType() == typeof(CustomSecurityException))
        {
            filterContext.ExceptionHandled = true;
            RequestContext rc = new RequestContext(filterContext.HttpContext, filterContext.RouteData);
            string url = RouteTable.Routes.GetVirtualPath(rc, new RouteValueDictionary(new { Controller = "NoAccess", action = "Index", message = filterContext.Exception.Message })).VirtualPath;
            filterContext.HttpContext.Response.Redirect(url, true);
        }
    }
}
A: 

This is something you need to handle on the browser. Try handling the error() on jQuery.ajax() call for example (and obviously don't return redirect..).

Maxwell Troy Milton King
A: 

You can verify if the request is an ajax request or not. You could for example do the following...

if (!filterContext.HttpContext.Request.IsAjaxRequest()){
    //Return a ViewResult
    //filterContext.ExceptionHandled = true;
    //filterContext.Result = new ViewResult { ViewName = "Error" ... };
}
else{
    //An ajax request. 
    //return a partial view
}

However, as Maxwell said you could let the exeption bubble up if it is an ajax request and handle the error on the client. You can setup globally a way of handling exceptions in ajax requests like it is described here

uvita
A: 

I would suggest letting the exception bubble up to the client and handle it like Maxwell suggested.

In our previous project we used a specific actionfilter for handling ajax errors (borrowed from Suteki Shop). Note that the response status is 500 (internal server error). An error status is required for the response in order to call de Error() delegate within a JQuery.ajax() call.

 public class HandleErrorWithAjaxAttribute : HandleErrorAttribute
    {
        public HandleErrorWithAjaxAttribute()
        {
            ShowStackTraceIfNotDebug = true;
        }

        public bool ShowStackTraceIfNotDebug { get; set; }

        public override void OnException(ExceptionContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                string content = ShowStackTraceIfNotDebug ||
                                 filterContext.HttpContext.IsDebuggingEnabled
                                     ?
                                         filterContext.Exception.StackTrace
                                     :
                                         string.Empty;
                filterContext.Result = new ContentResult
                                           {
                                               ContentType = MediaTypeNames.Text.Plain,
                                               Content = content
                                           };
                filterContext.HttpContext.Response.Status =
                    "500 " + filterContext.Exception.Message
                                 .Replace("\r", " ")
                                 .Replace("\n", " ");
                filterContext.ExceptionHandled = true;
                filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
            }
            else
            {
                base.OnException(filterContext);
            }
        }
    }
Rik
A: 

Did you try clearing the response? The controller may still be setting response content.

filterContext.HttpContext.Response.Clear()
filterContext.Result = new JsonResult { Data = new { Message = message } };
filterContext.HttpContext.Response.StatusCode = 500;
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
Ryan P