我的基本控制器中有一个可以处理我无法捕获的错误的捕获。它大致如下:
protected override void OnException(ExceptionContext filterContext)
{
// Bail if we can't do anything
if (filterContext == null)
return;
// log
var ex = filterContext.Exception ??
new Exception("No further information exists.");
LogException(ex);
filterContext.ExceptionHandled = true;
var data = new ErrorPresentation
{
ErrorMessage = HttpUtility.HtmlEncode(ex.Message),
TheException = ex
};
filterContext.Result = View("Error", data);
base.OnException(filterContext);
}
现在,如果错误发生在控制器中的 ,这会很有效。问题是如果在aspx页面呈现期间错误 (例如,在HtmlHelper方法中),整个错误视图将被呈现,就位于发生错误的页面。这意味着整个错误页面(MasterPage和all)都会在错误的页面中呈现。不完全是预期的行为。
我已尝试将View更改为RedirectToAction,但这不起作用,因为每个控制器都不存在路由(Home / Error,Configuration / Error等)。
如何让控件中的错误和页面上的错误都能正常工作?
答案 0 :(得分:12)
这是一个老问题,但是对于任何拼命搜索的人来说,这个代码适用于我,任何地方的例外 - 控制器,动作或动作结果,即视图或视图调用的任何助手。 (我是从史蒂夫桑德森的书中得到的,因为它归属于哪里):
protected override void OnException(ExceptionContext filterContext)
{
if (filterContext.ExceptionHandled)
return;
//Let the request know what went wrong
filterContext.Controller.TempData["Exception"] = filterContext.Exception;
//redirect to error handler
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(
new { controller = "Exception", action = "HandleError" }));
// Stop any other exception handlers from running
filterContext.ExceptionHandled = true;
// CLear out anything already in the response
filterContext.HttpContext.Response.Clear();
}
答案 1 :(得分:1)
您需要一种方法来跟踪页面所处的状态,以便您可以区分是否正在执行操作 - 在这种情况下您要替换结果 - 或执行结果 - 在这种情况下您想要丢弃响应的内容并为错误执行新的ViewResult。在基本控制器中保留标志将是处理此问题的一种方法。您也可以根据异常类型判断。我不确定会有多可靠。
一旦你弄清楚你可以做的状态:
var view = View("Error", data );
if (executingResult)
{
filterContext.HttpContext.Response.ClearContent();
view.ExecuteResult();
}
else
{
filterContext.Result = view;
base.OnException( filterContext );
}
评论:一般来说,我不主张这样做。我认为你的控制器操作应该向View保证它需要的所有数据都存在,或者你的View应该被防御性地写,以确保不会发生异常(特别是NullReferenceExceptions)。