Asp.net mvc中在基础控制器中重写OnException方法,但仍然会传播到Application_Error。

54

我正在尝试根据应用程序可能出现的某些错误返回视图而不是重定向到用户,我想在我的基础控制器中处理错误并记录它们,我不希望错误传播到我的Global.asax - Application_Error()方法,因为我希望这个方法处理我的应用程序中的任何其他错误,例如用户输入虚假的URL,有人找到了解决这个问题的方法吗?

注意:我保留了我的注释代码,因为我有一些解决问题的方法,这也显示了我可能需要处理多个异常...

编辑:如果我在这个OnException覆盖中发出RedirectToAction,一切都按预期工作,但我只想返回视图而不是重定向...

我的基础控制器方法是:

    protected override void OnException(ExceptionContext filterContext)
    {
        //dont interfere if the exception is already handled
        if (filterContext.ExceptionHandled)
            return;

        //let the next request know what went wrong
        filterContext.Controller.TempData["exception"] = filterContext.Exception;

        //log exception
        _logging.Error(User.Identity.Name, ExceptionHelper.BuildWebExceptionMessage(filterContext.Exception));


        //set up redirect to my global error handler
        //if (filterContext.Exception.GetType() == typeof(NoAccessException))
        //    filterContext.Result = View(new RouteValueDictionary
        //    (new { area = "", controller = "Error", action = "PublicError" }));

        //else {
        //Only return view, no need for redirection
        filterContext.Result = View(new RouteValueDictionary
        (new { area = "", controller = "Error", action = "NoAccess" }));
        //}
        //advise subsequent exception filters not to interfere and stop
        // asp.net from showing yellow screen of death
        filterContext.ExceptionHandled = true;

        //erase any output already generated
        filterContext.HttpContext.Response.Clear();

        //base.OnException(filterContext);
    }

这个方法应该处理我应用中可能出现的任何其他错误,我不希望上述错误被 Application_Error() 处理。

protected void Application_Error()
        {

            Exception exception = Server.GetLastError();
            // Log the exception.

            var logger = Container.Get<ILoggingService>();
            logger.Error(User.Identity.Name, ExceptionHelper.BuildWebExceptionMessage(exception));

            Response.Clear();

            HttpException httpException = exception as HttpException;

            RouteData routeData = new RouteData();
            routeData.Values.Add("controller", "Error");

            //if (httpException == null)
            //{
            routeData.Values.Add("action", "PublicError");
            //}
            //else //It's an Http Exception, Let's handle it.
            //{
            //    switch (httpException.GetHttpCode())
            //    {
            //        case 404:
            //            // Page not found.
            //            routeData.Values.Add("action", "HttpError404");
            //            break;
            //        case 500:
            //            // Server error.
            //            routeData.Values.Add("action", "HttpError500");
            //            break;

            //        // Here you can handle Views to other error codes.
            //        // I choose a General error template  
            //        default:
            //            routeData.Values.Add("action", "General");
            //            break;
            //    }
            //}

            // Pass exception details to the target error View.
            routeData.Values.Add("error", exception);

            // Clear the error on server.
            Server.ClearError();

            // Avoid IIS7 getting in the middle
            Response.TrySkipIisCustomErrors = true;

            // Call target Controller and pass the routeData.
            IController errorController = new ErrorController();
            errorController.Execute(new RequestContext(
                 new HttpContextWrapper(Context), routeData));
        }
1个回答

79
以下代码应该可行:
protected override void OnException(ExceptionContext filterContext)
{
    if (filterContext.ExceptionHandled)
    {
        return;
    }
    filterContext.Result = new ViewResult
    {
        ViewName = "~/Views/Shared/Error.aspx"
    };
    filterContext.ExceptionHandled = true;
}

还要确保此方法中不会抛出任何异常,否则它将传播到Application_Error


1
@Haroon,是的,绝对不会改变。它将是导致异常的初始URL,只是不再呈现黄色死亡屏幕,而是呈现自定义视图。 - Darin Dimitrov
2
也许我的问题很傻,但是有人能告诉我这个 OnException()(上面的代码)应该放在应用程序的哪里吗?在任何 controller 类中还是在 global.ascx.cs 中?放在哪里? - blue
1
@bluesky OnException() 是控制器类的一部分,可以被重写。 - Kyle
2
我发现设置其他一些属性,例如视图数据(类型为HandleErrorInfo的模型)和响应代码也非常有帮助。http://devproconnections.com/aspnet-mvc/aspnet-mvc-tutorial-handling-errors-and-exceptions - row1
@DarinDimitrov:如果这是一个Ajax请求怎么办?我像这样做的,if (ajaxReq) { filterContext.Result = new JsonResult() { Data = new { IsException = "true", RedirectUrl = "Error" }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } 然后在js中 $(document).ajaxSuccess(function (e, xhr, Opt, d) { var jD = JSON.parse(d); if (jD.IsException) { window.location.href = jD.RedirectUrl; } }); 但它将我重定向到'localhost:8787/Error'页面,显示404错误。 - Razort4x
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接