【问题标题】:Handle errors with ErrorController rather than a direct view使用 ErrorController 而不是直接视图处理错误
【发布时间】:2010-09-16 21:06:59
【问题描述】:

我试图了解 MVC 中的错误处理。 我正在寻找的是一种集中的方式来捕获错误,记录它们,如果可能的话解决它们,如果需要采取其他措施并最终向用户显示正确的视图。

我想我可以为此使用 [HandleError] 过滤器,但我看不到任何将其路由到控制器/动作的方法。我看到的唯一选择是将其直接指向一个视图。

【问题讨论】:

    标签: c# asp.net-mvc error-handling error-logging


    【解决方案1】:

    MVC 附带的HandleErrorAttribute 是一个非常基本的 IExceptionFilter。

    你有几个选择来实现我认为你想要的。

    您可以在操作/控制器上使用 [HandleError (Type=typeof(MyException),View="ErrorView")] 或实现您自己的

    HandleErrorAttribute 不是很复杂。我认为 MS 建议您复制此代码并进行修改以满足您的要求。

    OnException 覆盖让您可以通过 ExceptionContext 访问您可能需要的所有信息 - 控制器、操作、路由数据等。

    记得设置 ExceptionHandled。然后您可以将 filterContext.Result 设置为一个新的 RedirectToAction 实例,该实例重定向到您的 ErrorController 和操作 - 显然您可以使用属性公开特定的控制器和操作。

    【讨论】:

    • 标准的 HandleError 不允许我路由到我认为的控制器。所以这不是我需要的。我想我得自己动手了。这里没有什么好的资料可以参考吗?
    • Jep,注意到您回复中的链接有点晚了:P 谢谢。我现在正在创建一个 RerouteFilterAttribute。现在有很多试验/错误,但我会到达那里。
    【解决方案2】:

    Leppi,如果你想发送到 Action Result,你可以定义 Action 和 Controller 以在错误时重定向。这是一个很好的例子,但我个人不喜欢不使用自定义页面或 http 代码来编码

    这是我的 IExtenptionFilter 的示例。我的基本控制器有一个默认的 IExceptionFilter 来处理所有不受控制的错误。

    [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
        Justification = "This attribute is AllowMultiple = true and users might want to override behavior.")]
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class GenericExceptionHandlerFilter : ActionFilterAttribute, IExceptionFilter
    {
    
        public Type ExceptionType { get; set;}
        public string RedirectToAction { get; set;}
        public string RedirectToController { get; set;}
    
        protected bool ApplyFilter(ExceptionContext filterContext)
        {
            Type lExceptionType = filterContext.Exception.GetType();
            return (ExceptionType == null ||
                    lExceptionType.Equals(ExceptionType));
        }
    
    
        #region IExceptionFilter Members
        public void OnException(ExceptionContext filterContext)
        {
    
            if (ApplyFilter(filterContext))
            {
                IbfControllerLogger.Log(filterContext.Exception);
    
                filterContext.ExceptionHandled = true;
    
                #region Calculate Action Controller Error
                RouteValueDictionary lRoutes = new RouteValueDictionary(new
                    {
                        action = RedirectToAction,
                        controller = String.IsNullOrEmpty(RedirectToController) ? (string)filterContext.RouteData.Values["controller"] : RedirectToController
                    });
                UrlReWriterUtils.UrlReWriter(filterContext.Controller.ViewData, lRoutes);
                #endregion
    
                filterContext.Controller.TempData[TempDataName.C_TEMPDATA_EXCEPTIONERROR] = filterContext.Exception;
                filterContext.Result = new RedirectToRouteResult(lRoutes);
            }
        }
        #endregion
    

    【讨论】:

      【解决方案3】:

      为什么不创建您自己的从 ActionResult 派生的 ErrorResult?

      【讨论】:

        【解决方案4】:

        我在做什么(这可能是也可能不是一个好习惯)是这样的:

        发生错误时:

        • 如果我期望它并且可以处理它,我会做(使用 ELMAH 记录它)
        • 如果我期望它并且无法处理它,我将它记录到 ELMAH 并返回一个 ViewResult 这是我的错误页面
          • 包括错误描述、标准消息和返回我正在执行的操作的链接
        • 如果我没想到的话,我在基控制器类中对 OnError 的覆盖会执行上一步
        • ELMAH 会自动记录所有其他无法处理的错误,并且请求黄屏

        我的大部分通用错误处理都放在我所有控制器的基类中。唯一的问题是我必须在基类中手动设置控制器和操作值,以便它可以为错误页面中的重定向生成 ActionLink。

        【讨论】:

        • 过滤器似乎是处理错误而不是覆盖 onerror 的方法。它们与控制器很好地正交。
        • 感谢反馈,但我宁愿不将错误处理与我的基本控制器放在同一个类中。这将使我的基类的可重用性降低,因为每个站点的错误处理逻辑通常都不同。我目前正在创建一个 RerouteErrorAttribute 过滤器来完成这项工作。
        猜你喜欢
        • 2021-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多