asp.net-mvc - 如何让 ELMAH 与 ASP.NET MVC [HandleError] 属性一起使用?

标签 asp.net-mvc logging elmah

我尝试使用 ELMAH 记录 ASP.NET MVC 应用程序中的错误,但是当我在 Controller 上使用 [HandleError] 属性时,ELMAH 在发生错误时不会记录任何错误。

正如我猜测的那样,因为 ELMAH 只记录未处理的错误,并且 [HandleError] 属性正在处理错误,因此不需要记录它。

我该如何修改或如何修改该属性,以便 ELMAH 知道存在错误并记录它..

编辑:让我确保每个人都理解,我知道我可以修改该属性,但这不是我要问的问题...当使用handleerror属性时,ELMAH会被绕过,这意味着它不会看到有一个错误,因为它已经被属性处理了...我要问的是有没有一种方法可以让 ELMAH 看到错误并记录它,即使属性处理了它...我到处搜索但没有查看调用的任何方法以强制其记录错误....

最佳答案

您可以子类化 HandleErrorAttribute并覆盖其 OnException成员(无需复制),以便仅在基本实现处理异常时才使用 ELMAH 记录异常。您需要的最少代码量如下:

using System.Web.Mvc;
using Elmah;

public class HandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
        base.OnException(context);
        if (!context.ExceptionHandled) 
            return;
        var httpContext = context.HttpContext.ApplicationInstance.Context;
        var signal = ErrorSignal.FromContext(httpContext);
        signal.Raise(context.Exception, httpContext);
    }
}

首先调用基本实现,使其有机会将异常标记为正在处理。只有这样才会发出异常信号。上面的代码很简单,如果在 HttpContext 可能不可用的环境中使用,例如测试,可能会导致问题。因此,您将需要更具防御性的代码(代价是稍微更长):

using System.Web;
using System.Web.Mvc;
using Elmah;

public class HandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
        base.OnException(context);
        if (!context.ExceptionHandled       // if unhandled, will be logged anyhow
            || TryRaiseErrorSignal(context) // prefer signaling, if possible
            || IsFiltered(context))         // filtered?
            return;

        LogException(context);
    }

    private static bool TryRaiseErrorSignal(ExceptionContext context)
    {
        var httpContext = GetHttpContextImpl(context.HttpContext);
        if (httpContext == null)
            return false;
        var signal = ErrorSignal.FromContext(httpContext);
        if (signal == null)
            return false;
        signal.Raise(context.Exception, httpContext);
        return true;
    }

    private static bool IsFiltered(ExceptionContext context)
    {
        var config = context.HttpContext.GetSection("elmah/errorFilter")
                        as ErrorFilterConfiguration;

        if (config == null)
            return false;

        var testContext = new ErrorFilterModule.AssertionHelperContext(
                              context.Exception, 
                              GetHttpContextImpl(context.HttpContext));
        return config.Assertion.Test(testContext);
    }

    private static void LogException(ExceptionContext context)
    {
        var httpContext = GetHttpContextImpl(context.HttpContext);
        var error = new Error(context.Exception, httpContext);
        ErrorLog.GetDefault(httpContext).Log(error);
    }

    private static HttpContext GetHttpContextImpl(HttpContextBase context)
    {
        return context.ApplicationInstance.Context;
    }
}

第二个版本将尝试使用 error signaling首先从 ELMAH 开始,其中涉及完全配置的管道,如日志记录、邮件、过滤等等。如果失败,它会尝试查看是否应过滤该错误。如果不是,则仅记录错误。此实现不处理邮件通知。如果可以发出异常信号,则将发送一封邮件(如果已配置)。

您可能还需要注意,如果多个 HandleErrorAttribute 实例有效,则不会发生重复日志记录,但以上两个示例应该可以帮助您入门。

关于asp.net-mvc - 如何让 ELMAH 与 ASP.NET MVC [HandleError] 属性一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/766610/

相关文章:

asp.net-mvc - 你应该在哪里定期登录 asp.net-mvc ?你应该使用ELMAH吗?

asp.net-mvc-3 - asp.net mvc 3 和 elmah.axd - 另一个 404

asp.net-mvc - 手动授予访问 token MVC Web API

c# - 如何通过自定义Attribute获取和修改属性值?

python - 找不到记录器 "deluge"的处理程序

sql - 自动运行 ELMAH 数据库脚本

c# - 无法使 httpErrors 工作

c# - 一次在多个表中插入/更新数据的最佳实践

java - 用java创建一个Logger库

python - 如何临时重定向 Python 中日志记录的输出?