开发者

asp.net mvc custom exception filter to force a return of full view, not partial

开发者 https://www.devze.com 2022-12-20 12:59 出处:网络
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

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);
        }
    }
}


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..).


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);
            }
        }
    }


I use the OnFailure hanlder in form tag.

<form id="AJAXForm" method="post" action=""
   onsubmit="Sys.Mvc.AsyncForm.handleSubmit(this, new Sys.UI.DomEvent(event),
   { insertionMode: Sys.Mvc.InsertionMode.replace, httpMethod: 'POST', 
   updateTargetId: 'myPartialPage', onSuccess: Function.createDelegate(this, ajaxFormSucced),
   onFailure: Function.createDelegate(this, ajaxFormFailure) });" >

... function ajaxFormSucced(){ // Code for success } function ajaxFormFailure(){ // Code for failure }


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


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;


This link helped me Handling ASP.NET MVC exceptions when posting to the controller via Ajax using jQuery

Lastly, When testing the javascript function, start with alert on the first line. Any javascript errors in your function are likely to stop the function in mid execution without javascript error feedback via the browser (depending on your setup).


This will help you.

Just add .IsAjaxRequest extension method and return 403 status code to browser, jquery ajaxError will handle it redirecting to login page


As Maxwell says, handle on the client, using something like this

function handleError(ajaxContext) {
    // Load parent
}

@using (Ajax.BeginForm("Index", "Home", new AjaxOptions
{         
    UpdateTargetId = "MyDiv",
    OnFailure = "handleError"
}))

What you must do though is make sure in the controller ActionResult code for NoAccess contains the following code, so that your ajax error is triggered.

HttpContext.Response.StatusCode = 401;
0

精彩评论

暂无评论...
验证码 换一张
取 消