ASP.NET MVC中全局错误处理(控制器之外)

7
假设我在ASP.NET MVC站点的母版页中放置了以下代码:
throw new ApplicationException("TEST");

即使在我的控制器上放置了 [HandleError] 属性,这个异常仍然会冒泡。我该如何处理这样的错误?我希望能够路由到一个错误页面,并仍然能够记录异常详细信息。
如何处理这种情况最好的方法是什么?
编辑:我正在考虑的一个解决方案是添加一个新的控制器:UnhandledErrorController。我可以在 Global.asax 中添加一个 Application_Error 方法,然后重定向到这个控制器(它决定如何处理异常)吗?
注意:customErrors web.config 元素中的 defaultRedirect 不会传递异常信息。

1
ApplicationException现在实际上是一种反模式,请参见:http://blogs.msdn.com/kcwalina/archive/2006/06/23/644822.aspx考虑只抛出新的Exception(...); - Stephanvs
你可能会发现这篇文章很有用:http://blog.ploeh.dk/2009/12/01/GlobalErrorHandlingInASPNETMVC.aspx - Mark Seemann
这是一个很棒的答案! - Peter Morris
4个回答

10

启用自定义错误:

<customErrors mode="On" defaultRedirect="~/Error">
    <error statusCode="401" redirect="~/Error/Unauthorized" />
    <error statusCode="404" redirect="~/Error/NotFound" />
</customErrors>

并且重定向到自定义的错误控制器:

[HandleError]
public class ErrorController : BaseController
{
    public ErrorController ()
    {
    }

    public ActionResult Index ()
    {
        Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        return View ("Error");
    }

    public ActionResult Unauthorized ()
    {
        Response.StatusCode = (int)HttpStatusCode.Unauthorized;
        return View ("Error401");
    }

    public ActionResult NotFound ()
    {
        string url = GetStaticRoute (Request.QueryString["aspxerrorpath"] ?? Request.Path);
        if (!string.IsNullOrEmpty (url))
        {
            Notify ("Due to a new web site design the page you were looking for no longer exists.", false);
            return new MovedPermanentlyResult (url);
        }

        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View ("Error404");
    }
}

我需要将自定义错误放在webconfig的哪个部分? - Zapnologica

5
由于MVC是建立在ASP.NET之上的,您应该能够像Web Forms一样在web.config中定义全局错误页面。请参考此链接
   <customErrors mode="On" defaultRedirect="~/ErrorHandler" />

7
那么我该如何获取异常详细信息? - user10789

5
您可以创建一个过滤器,该过滤器在OnActionExecuted方法中查找异常:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class WatchExceptionAttribute : ActionFilterAttribute {
  public override void OnActionExecuted(ActionExecutedContext filterContext) {
    if (filterContext.Exception != null) {
      // do your thing here.
    }
  }
}

然后你可以在控制器或操作方法上放置[WatchException],它将记录异常。如果你有很多控制器,那可能会很繁琐,所以如果你有一个通用的基础控制器,你可以在那里重写OnActionExecuted并执行相同的操作。我更喜欢过滤器方法。


1

关于显示哪个页面,您需要在web.config中创建一个customErrors section,并将其设置为您想要处理的状态代码。

例如:

<customErrors defaultRedirect="GenericError.htm" mode="RemoteOnly">
  <error statusCode="500" redirect="InternalError.htm"/>
</customErrors>

就记录异常而言,我建议使用 ELMAH。 它与 ASP.NET MVC 网站集成得很好。

是的,除非在配置文件中启用了customErrors,否则HandleError将不会实际执行任何操作。 - swilliams
我仍然需要能够检索和记录异常详细信息。最好的情况是,我可以在默认重定向指向的控制器操作中执行此操作。 - user10789
@iguananet 这就是 ELMAH 的作用。如果你想要单独实现它,那就是完全不同的问题,但它非常有效。我强烈建议你试一试。 - Joseph
@Joseph-- 谢谢,但我想找到最简单的方法,在不引入任何依赖项或新项目的情况下完成它。 - user10789

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