使用全局日志记录时,MVC [HandleError] HandleErrorAttribute被调用两次

Pau*_*rge 10 asp.net error-handling asp.net-mvc asp.net-mvc-3

在我使用的MVC3 Web应用程序中

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
}
Run Code Online (Sandbox Code Playgroud)

应用全局错误处理,如果发生未处理的异常,则向用户显示"错误"视图.

对于一个特定的视图,如果通过使用装饰方法发生未处理的异常,我还希望显示不同的错误视图 [HandleError(View = "SpecialError")].这很好.

然后我想添加未处理异常的全局日志记录.我创建了一个带有日志代码的自定义HandleError属性:

public class MyHandleErrorAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext context)
        {
            // Write to log code
            base.OnException(context);
        }
    }
Run Code Online (Sandbox Code Playgroud)

并更新了RegisterGlobalFilters和方法修饰以改为使用此属性名称.这通常有效,但是在使用MyHandleError(View = "SpecialError")]OnException方法修饰的方法中发生异常时会调用两次.我原先假设用这个属性装饰方法取代了全局处理程序,但它似乎只是添加到了(这更有意义,但它不是我想要的).通过两次调用OnException,将记录两次相同的异常,这不应该发生.我不认为OnException被调用两次,因为它是一个自定义属性 - 我相信这也发生在标准的HandleError属性上,它现在只是在我创建它的记录时可见.

最终,我想记录所有未处理的异常(一次),同时保留[HandleError]提供的功能,特别是为特定方法异常设置不同的视图.这样做有干净的方法吗?

Pau*_*rge 9

我相信我自己找到了一个干净的解决方案.扩展HandleError似乎是一个好主意,但现在我认为这是朝着错误方向迈出的一步.我不想以不同的方式处理任何错误,只需在HandleError选择它们之前将异常写入一次.因此,默认的HandleError可以按原样保留.虽然可以多次调用OnException,但在HandleErrorAttribute的标准实现中它似乎完全是良性的.

相反,我创建了一个异常日志过滤器

public class LoggedExceptionFilter : IExceptionFilter
    {
        public void OnException(ExceptionContext filterContext)
        {
            // logging code
        }
    }
Run Code Online (Sandbox Code Playgroud)

它不需要太继承,FilterAttribute因为它只是在RegisterGlobalFilters中与HandleErrorAttribute一起注册一次.

 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new LoggedExceptionFilter());
        filters.Add(new HandleErrorAttribute());
    }
Run Code Online (Sandbox Code Playgroud)

这样可以在不更改标准[HandleError]功能的情况下巧妙地记录异常