ASP.NET MVC中的通用基本控制器错误处理问题

时间:2009-07-22 15:25:02

标签: asp.net-mvc error-handling

我的基本控制器中有一个可以处理我无法捕获的错误的捕获。它大致如下:

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等)。

如何让控件中的错误和页面上的错误都能正常工作?

2 个答案:

答案 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)。