如何让ELMAH与ASP一起工作。净MVC[HandleError]属性?

时间:2022-05-04 11:50:54

I am trying to use ELMAH to log errors in my ASP.NET MVC application, however when I use the [HandleError] attribute on my controllers ELMAH doesn't log any errors when they occur.

我正在尝试使用ELMAH在我的ASP中记录错误。不过,当我在控制器上使用[HandleError]属性时,ELMAH不会记录任何错误。

As I am guessing its because ELMAH only logs unhandled errors and the [HandleError] attribute is handling the error so thus no need to log it.

我猜是因为ELMAH只记录未处理的错误,而[HandleError]属性正在处理错误,因此不需要记录错误。

How do I modify or how would I go about modifying the attribute so ELMAH can know that there was an error and log it..

如何修改或修改属性,以便ELMAH知道有错误并记录它。

Edit: Let me make sure everyone understands, I know I can modify the attribute thats not the question I'm asking... ELMAH gets bypassed when using the handleerror attribute meaning it won't see that there was an error because it was handled already by the attribute... What I am asking is there a way to make ELMAH see the error and log it even though the attribute handled it...I searched around and don't see any methods to call to force it to log the error....

编辑:让我确保每个人都理解,我知道我可以修改属性,这不是我要问的问题……ELMAH在使用handleerror属性时被忽略,这意味着它不会看到有错误,因为它已经被属性处理了……我想问的是,有一种方法可以让ELMAH看到错误并记录它,即使属性处理了它……我搜索四周,没有看到任何方法调用迫使其日志错误....

8 个解决方案

#1


494  

You can subclass HandleErrorAttribute and override its OnException member (no need to copy) so that it logs the exception with ELMAH and only if the base implementation handles it. The minimal amount of code you need is as follows:

您可以子类化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);
    }
}

The base implementation is invoked first, giving it a chance to mark the exception as being handled. Only then is the exception signaled. The above code is simple and may cause issues if used in an environment where the HttpContext may not be available, such as testing. As a result, you will want code that is that is more defensive (at the cost of being slightly longer):

首先调用基本实现,使其有机会将异常标记为正在处理。只有这样,异常才会发出信号。上面的代码很简单,如果在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;
    }
}

This second version will try to use error signaling from ELMAH first, which involves the fully configured pipeline like logging, mailing, filtering and what have you. Failing that, it attempts to see whether the error should be filtered. If not, the error is simply logged. This implementation does not handle mail notifications. If the exception can be signaled then a mail will be sent if configured to do so.

第二个版本将首先尝试使用来自ELMAH的错误信号,其中包括完整配置的管道,如日志、邮件、过滤等等。如果做不到这一点,它将尝试查看是否应该过滤错误。如果没有,则只记录错误。此实现不处理邮件通知。如果异常可以发出信号,则如果配置为这样做,则将发送邮件。

You may also have to take care that if multiple HandleErrorAttribute instances are in effect then duplicate logging does not occur, but the above two examples should get your started.

您可能还需要注意,如果多个HandleErrorAttribute实例是有效的,那么不会发生重复日志记录,但是上面的两个示例应该可以开始了。

#2


296  

Sorry, but I think the accepted answer is an overkill. All you need to do is this:

对不起,但我认为大家都接受的答案是“过犹不及”。你所需要做的就是:

public class ElmahHandledErrorLoggerFilter : IExceptionFilter
{
    public void OnException (ExceptionContext context)
    {
        // Log only handled exceptions, because all other will be caught by ELMAH anyway.
        if (context.ExceptionHandled)
            ErrorSignal.FromCurrentContext().Raise(context.Exception);
    }
}

and then register it (order is important) in Global.asax.cs:

然后在Global.asax.cs中注册(顺序很重要):

public static void RegisterGlobalFilters (GlobalFilterCollection filters)
{
    filters.Add(new ElmahHandledErrorLoggerFilter());
    filters.Add(new HandleErrorAttribute());
}

#3


14  

There is now an ELMAH.MVC package in NuGet that includes an improved solution by Atif and also a controller that handles the elmah interface within MVC routing (no need to use that axd anymore)
The problem with that solution (and with all the ones here) is that one way or another the elmah error handler is actually handling the error, ignoring what you might want to set up as a customError tag or through ErrorHandler or your own error handler
The best solution IMHO is to create a filter that will act at the end of all the other filters and log the events that have been handled already. The elmah module should take care of loging the other errors that are unhandled by the application. This will also allow you to use the health monitor and all the other modules that can be added to asp.net to look at error events

现在有了埃尔玛。NuGet MVC包中包括一种改进解决方案,爱迪和控制器处理elmah接口在MVC路由(不需要使用axd了)问题的解决方案(和所有的)是这样或那样的方式elmah错误处理程序是处理错误,忽略您可能希望设置为customError标记或通过ErrorHandler或您自己的错误处理程序设置的内容,最好的解决方案IMHO是创建一个过滤器,该过滤器将在所有其他过滤器的末尾执行,并记录已处理的事件。elmah模块应该负责登录应用程序未处理的其他错误。这还允许您使用health monitor和可以添加到asp.net的所有其他模块来查看错误事件

I wrote this looking with reflector at the ErrorHandler inside elmah.mvc

我用reflector查看elmah.mvc中的ErrorHandler写了这篇文章

public class ElmahMVCErrorFilter : IExceptionFilter
{
   private static ErrorFilterConfiguration _config;

   public void OnException(ExceptionContext context)
   {
       if (context.ExceptionHandled) //The unhandled ones will be picked by the elmah module
       {
           var e = context.Exception;
           var context2 = context.HttpContext.ApplicationInstance.Context;
           //TODO: Add additional variables to context.HttpContext.Request.ServerVariables for both handled and unhandled exceptions
           if ((context2 == null) || (!_RaiseErrorSignal(e, context2) && !_IsFiltered(e, context2)))
           {
            _LogException(e, context2);
           }
       }
   }

   private static bool _IsFiltered(System.Exception e, System.Web.HttpContext context)
   {
       if (_config == null)
       {
           _config = (context.GetSection("elmah/errorFilter") as ErrorFilterConfiguration) ?? new ErrorFilterConfiguration();
       }
       var context2 = new ErrorFilterModule.AssertionHelperContext((System.Exception)e, context);
       return _config.Assertion.Test(context2);
   }

   private static void _LogException(System.Exception e, System.Web.HttpContext context)
   {
       ErrorLog.GetDefault((System.Web.HttpContext)context).Log(new Elmah.Error((System.Exception)e, (System.Web.HttpContext)context));
   }


   private static bool _RaiseErrorSignal(System.Exception e, System.Web.HttpContext context)
   {
       var signal = ErrorSignal.FromContext((System.Web.HttpContext)context);
       if (signal == null)
       {
           return false;
       }
       signal.Raise((System.Exception)e, (System.Web.HttpContext)context);
       return true;
   }
}

Now, in your filter config you want to do something like this:

现在,在您的过滤器配置中,您想要做如下操作:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //These filters should go at the end of the pipeline, add all error handlers before
        filters.Add(new ElmahMVCErrorFilter());
    }

Notice that I left a comment there to remind people that if they want to add a global filter that will actually handle the exception it should go BEFORE this last filter, otherwise you run into the case where the unhandled exception will be ignored by the ElmahMVCErrorFilter because it hasn't been handled and it should be loged by the Elmah module but then the next filter marks the exception as handled and the module ignores it, resulting on the exception never making it into elmah.

注意到我留言提醒人们,如果他们想要添加一个全球过滤器,应该会处理异常之前最后一个过滤器,否则你将被忽略的情况下,未处理的异常ElmahMVCErrorFilter因为它尚未处理,应该由Elmah模块日志然后下一个过滤器是异常处理和模块忽略它,从来没有让它变成Elmah产生的异常。

Now, make sure the appsettings for elmah in your webconfig look something like this:

现在,确保你的webconfig中的elmah的appsettings是这样的:

<add key="elmah.mvc.disableHandler" value="false" /> <!-- This handles elmah controller pages, if disabled elmah pages will not work -->
<add key="elmah.mvc.disableHandleErrorFilter" value="true" /> <!-- This uses the default filter for elmah, set to disabled to use our own -->
<add key="elmah.mvc.requiresAuthentication" value="false" /> <!-- Manages authentication for elmah pages -->
<add key="elmah.mvc.allowedRoles" value="*" /> <!-- Manages authentication for elmah pages -->
<add key="elmah.mvc.route" value="errortracking" /> <!-- Base route for elmah pages -->

The important one here is "elmah.mvc.disableHandleErrorFilter", if this is false it will use the handler inside elmah.mvc that will actually handle the exception by using the default HandleErrorHandler that will ignore your customError settings

这里最重要的是“elmah.mvc”。disableHandleErrorFilter”,如果是false,它将使用elmah中的处理程序。通过使用默认HandleErrorHandler来处理异常的mvc,它将忽略customError设置

This setup allows you to set your own ErrorHandler tags in classes and views, while still loging those errors through the ElmahMVCErrorFilter, adding a customError configuration to your web.config through the elmah module, even writing your own Error Handlers. The only thing you need to do is remember to not add any filters that will actually handle the error before the elmah filter we've written. And I forgot to mention: no duplicates in elmah.

这个设置允许您在类和视图中设置自己的ErrorHandler标记,同时还可以通过ElmahMVCErrorFilter来记录这些错误,在web上添加一个自定义错误配置。通过elmah模块进行配置,甚至编写自己的错误处理程序。您需要做的唯一一件事是记住,在我们编写的elmah过滤器之前,不要添加任何实际处理错误的过滤器。我忘了说:埃尔玛没有复制品。

#4


7  

You can take the code above and go one step further by introducing a custom controller factory that injects the HandleErrorWithElmah attribute into every controller.

您可以使用上面的代码,并通过引入一个自定义控制器工厂来更进一步,该工厂将HandleErrorWithElmah属性注入到每个控制器中。

For more infomation check out my blog series on logging in MVC. The first article covers getting Elmah set up and running for MVC.

要了解更多信息,请查看我关于MVC登录的博客系列。第一篇文章介绍了如何为MVC设置和运行Elmah。

There is a link to downloadable code at the end of the article. Hope that helps.

本文末尾有一个可下载代码的链接。希望有帮助。

http://dotnetdarren.wordpress.com/

http://dotnetdarren.wordpress.com/

#5


6  

I'm new in ASP.NET MVC. I faced the same problem, the following is my workable in my Erorr.vbhtml (it work if you only need to log the error using Elmah log)

我刚在ASP。净MVC。我也遇到过同样的问题,以下是我在工作中可以做到的。vbhtml(如果您只需要使用Elmah日志记录错误,那么它可以工作)

@ModelType System.Web.Mvc.HandleErrorInfo

    @Code
        ViewData("Title") = "Error"
        Dim item As HandleErrorInfo = CType(Model, HandleErrorInfo)
        //To log error with Elmah
        Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(New Elmah.Error(Model.Exception, HttpContext.Current))
    End Code

<h2>
    Sorry, an error occurred while processing your request.<br />

    @item.ActionName<br />
    @item.ControllerName<br />
    @item.Exception.Message
</h2> 

It is simply!

这很简单!

#6


6  

A completely alternative solution is to not use the MVC HandleErrorAttribute, and instead rely on ASP.Net error handling, which Elmah is designed to work with.

一个完全替代的解决方案是不使用MVC HandleErrorAttribute,而是依赖于ASP。Net错误处理,这是Elmah设计用来处理的。

You need to remove the default global HandleErrorAttribute from App_Start\FilterConfig (or Global.asax), and then set up an error page in your Web.config:

您需要从App_Start\FilterConfig(或Global.asax)中删除默认的全局HandleErrorAttribute,然后在您的Web.config中设置一个错误页面。

<customErrors mode="RemoteOnly" defaultRedirect="~/error/" />

Note, this can be an MVC routed URL, so the above would redirect to the ErrorController.Index action when an error occurs.

注意,这可以是一个MVC路由URL,因此上面的内容将重定向到ErrorController。发生错误时的索引操作。

#7


5  

For me it was very important to get email logging working. After some time I discover that this need only 2 lines of code more in Atif example.

对我来说,让电子邮件记录工作起来很重要。经过一段时间,我发现在Atif示例中只需要2行代码。

public class HandleErrorWithElmahAttribute : HandleErrorAttribute
{
    static ElmahMVCMailModule error_mail_log = new ElmahMVCMailModule();

    public override void OnException(ExceptionContext context)
    {
        error_mail_log.Init(HttpContext.Current.ApplicationInstance);
        [...]
    }
    [...]
}

I hope this will help someone :)

我希望这能帮助一些人:

#8


2  

This is exactly what I needed for my MVC site configuration!

这正是我需要的MVC站点配置!

I added a little modification to the OnException method to handle multiple HandleErrorAttribute instances, as suggested by Atif Aziz:

我对OnException方法进行了一点修改,以处理多个HandleErrorAttribute实例,正如Atif Aziz所建议的:

bear in mind that you may have to take care that if multiple HandleErrorAttribute instances are in effect then duplicate logging does not occur.

请记住,如果多个HandleErrorAttribute实例生效,那么就不会发生重复日志记录。

I simply check context.ExceptionHandled before invoking the base class, just to know if someone else handled the exception before current handler.
It works for me and I post the code in case someone else needs it and to ask if anyone knows if I overlooked anything.

我只是检查上下文。在调用基类之前处理exceptionhandle,只需要知道是否有人在当前处理程序之前处理了这个异常。它适用于我,我发布代码,以防别人需要它,并询问是否有人知道我忽略了什么。

Hope it is useful:

希望它是有用的:

public override void OnException(ExceptionContext context)
{
    bool exceptionHandledByPreviousHandler = context.ExceptionHandled;

    base.OnException(context);

    Exception e = context.Exception;
    if (exceptionHandledByPreviousHandler
        || !context.ExceptionHandled  // if unhandled, will be logged anyhow
        || RaiseErrorSignal(e)        // prefer signaling, if possible
        || IsFiltered(context))       // filtered?
        return;

    LogException(e);
}

#1


494  

You can subclass HandleErrorAttribute and override its OnException member (no need to copy) so that it logs the exception with ELMAH and only if the base implementation handles it. The minimal amount of code you need is as follows:

您可以子类化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);
    }
}

The base implementation is invoked first, giving it a chance to mark the exception as being handled. Only then is the exception signaled. The above code is simple and may cause issues if used in an environment where the HttpContext may not be available, such as testing. As a result, you will want code that is that is more defensive (at the cost of being slightly longer):

首先调用基本实现,使其有机会将异常标记为正在处理。只有这样,异常才会发出信号。上面的代码很简单,如果在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;
    }
}

This second version will try to use error signaling from ELMAH first, which involves the fully configured pipeline like logging, mailing, filtering and what have you. Failing that, it attempts to see whether the error should be filtered. If not, the error is simply logged. This implementation does not handle mail notifications. If the exception can be signaled then a mail will be sent if configured to do so.

第二个版本将首先尝试使用来自ELMAH的错误信号,其中包括完整配置的管道,如日志、邮件、过滤等等。如果做不到这一点,它将尝试查看是否应该过滤错误。如果没有,则只记录错误。此实现不处理邮件通知。如果异常可以发出信号,则如果配置为这样做,则将发送邮件。

You may also have to take care that if multiple HandleErrorAttribute instances are in effect then duplicate logging does not occur, but the above two examples should get your started.

您可能还需要注意,如果多个HandleErrorAttribute实例是有效的,那么不会发生重复日志记录,但是上面的两个示例应该可以开始了。

#2


296  

Sorry, but I think the accepted answer is an overkill. All you need to do is this:

对不起,但我认为大家都接受的答案是“过犹不及”。你所需要做的就是:

public class ElmahHandledErrorLoggerFilter : IExceptionFilter
{
    public void OnException (ExceptionContext context)
    {
        // Log only handled exceptions, because all other will be caught by ELMAH anyway.
        if (context.ExceptionHandled)
            ErrorSignal.FromCurrentContext().Raise(context.Exception);
    }
}

and then register it (order is important) in Global.asax.cs:

然后在Global.asax.cs中注册(顺序很重要):

public static void RegisterGlobalFilters (GlobalFilterCollection filters)
{
    filters.Add(new ElmahHandledErrorLoggerFilter());
    filters.Add(new HandleErrorAttribute());
}

#3


14  

There is now an ELMAH.MVC package in NuGet that includes an improved solution by Atif and also a controller that handles the elmah interface within MVC routing (no need to use that axd anymore)
The problem with that solution (and with all the ones here) is that one way or another the elmah error handler is actually handling the error, ignoring what you might want to set up as a customError tag or through ErrorHandler or your own error handler
The best solution IMHO is to create a filter that will act at the end of all the other filters and log the events that have been handled already. The elmah module should take care of loging the other errors that are unhandled by the application. This will also allow you to use the health monitor and all the other modules that can be added to asp.net to look at error events

现在有了埃尔玛。NuGet MVC包中包括一种改进解决方案,爱迪和控制器处理elmah接口在MVC路由(不需要使用axd了)问题的解决方案(和所有的)是这样或那样的方式elmah错误处理程序是处理错误,忽略您可能希望设置为customError标记或通过ErrorHandler或您自己的错误处理程序设置的内容,最好的解决方案IMHO是创建一个过滤器,该过滤器将在所有其他过滤器的末尾执行,并记录已处理的事件。elmah模块应该负责登录应用程序未处理的其他错误。这还允许您使用health monitor和可以添加到asp.net的所有其他模块来查看错误事件

I wrote this looking with reflector at the ErrorHandler inside elmah.mvc

我用reflector查看elmah.mvc中的ErrorHandler写了这篇文章

public class ElmahMVCErrorFilter : IExceptionFilter
{
   private static ErrorFilterConfiguration _config;

   public void OnException(ExceptionContext context)
   {
       if (context.ExceptionHandled) //The unhandled ones will be picked by the elmah module
       {
           var e = context.Exception;
           var context2 = context.HttpContext.ApplicationInstance.Context;
           //TODO: Add additional variables to context.HttpContext.Request.ServerVariables for both handled and unhandled exceptions
           if ((context2 == null) || (!_RaiseErrorSignal(e, context2) && !_IsFiltered(e, context2)))
           {
            _LogException(e, context2);
           }
       }
   }

   private static bool _IsFiltered(System.Exception e, System.Web.HttpContext context)
   {
       if (_config == null)
       {
           _config = (context.GetSection("elmah/errorFilter") as ErrorFilterConfiguration) ?? new ErrorFilterConfiguration();
       }
       var context2 = new ErrorFilterModule.AssertionHelperContext((System.Exception)e, context);
       return _config.Assertion.Test(context2);
   }

   private static void _LogException(System.Exception e, System.Web.HttpContext context)
   {
       ErrorLog.GetDefault((System.Web.HttpContext)context).Log(new Elmah.Error((System.Exception)e, (System.Web.HttpContext)context));
   }


   private static bool _RaiseErrorSignal(System.Exception e, System.Web.HttpContext context)
   {
       var signal = ErrorSignal.FromContext((System.Web.HttpContext)context);
       if (signal == null)
       {
           return false;
       }
       signal.Raise((System.Exception)e, (System.Web.HttpContext)context);
       return true;
   }
}

Now, in your filter config you want to do something like this:

现在,在您的过滤器配置中,您想要做如下操作:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //These filters should go at the end of the pipeline, add all error handlers before
        filters.Add(new ElmahMVCErrorFilter());
    }

Notice that I left a comment there to remind people that if they want to add a global filter that will actually handle the exception it should go BEFORE this last filter, otherwise you run into the case where the unhandled exception will be ignored by the ElmahMVCErrorFilter because it hasn't been handled and it should be loged by the Elmah module but then the next filter marks the exception as handled and the module ignores it, resulting on the exception never making it into elmah.

注意到我留言提醒人们,如果他们想要添加一个全球过滤器,应该会处理异常之前最后一个过滤器,否则你将被忽略的情况下,未处理的异常ElmahMVCErrorFilter因为它尚未处理,应该由Elmah模块日志然后下一个过滤器是异常处理和模块忽略它,从来没有让它变成Elmah产生的异常。

Now, make sure the appsettings for elmah in your webconfig look something like this:

现在,确保你的webconfig中的elmah的appsettings是这样的:

<add key="elmah.mvc.disableHandler" value="false" /> <!-- This handles elmah controller pages, if disabled elmah pages will not work -->
<add key="elmah.mvc.disableHandleErrorFilter" value="true" /> <!-- This uses the default filter for elmah, set to disabled to use our own -->
<add key="elmah.mvc.requiresAuthentication" value="false" /> <!-- Manages authentication for elmah pages -->
<add key="elmah.mvc.allowedRoles" value="*" /> <!-- Manages authentication for elmah pages -->
<add key="elmah.mvc.route" value="errortracking" /> <!-- Base route for elmah pages -->

The important one here is "elmah.mvc.disableHandleErrorFilter", if this is false it will use the handler inside elmah.mvc that will actually handle the exception by using the default HandleErrorHandler that will ignore your customError settings

这里最重要的是“elmah.mvc”。disableHandleErrorFilter”,如果是false,它将使用elmah中的处理程序。通过使用默认HandleErrorHandler来处理异常的mvc,它将忽略customError设置

This setup allows you to set your own ErrorHandler tags in classes and views, while still loging those errors through the ElmahMVCErrorFilter, adding a customError configuration to your web.config through the elmah module, even writing your own Error Handlers. The only thing you need to do is remember to not add any filters that will actually handle the error before the elmah filter we've written. And I forgot to mention: no duplicates in elmah.

这个设置允许您在类和视图中设置自己的ErrorHandler标记,同时还可以通过ElmahMVCErrorFilter来记录这些错误,在web上添加一个自定义错误配置。通过elmah模块进行配置,甚至编写自己的错误处理程序。您需要做的唯一一件事是记住,在我们编写的elmah过滤器之前,不要添加任何实际处理错误的过滤器。我忘了说:埃尔玛没有复制品。

#4


7  

You can take the code above and go one step further by introducing a custom controller factory that injects the HandleErrorWithElmah attribute into every controller.

您可以使用上面的代码,并通过引入一个自定义控制器工厂来更进一步,该工厂将HandleErrorWithElmah属性注入到每个控制器中。

For more infomation check out my blog series on logging in MVC. The first article covers getting Elmah set up and running for MVC.

要了解更多信息,请查看我关于MVC登录的博客系列。第一篇文章介绍了如何为MVC设置和运行Elmah。

There is a link to downloadable code at the end of the article. Hope that helps.

本文末尾有一个可下载代码的链接。希望有帮助。

http://dotnetdarren.wordpress.com/

http://dotnetdarren.wordpress.com/

#5


6  

I'm new in ASP.NET MVC. I faced the same problem, the following is my workable in my Erorr.vbhtml (it work if you only need to log the error using Elmah log)

我刚在ASP。净MVC。我也遇到过同样的问题,以下是我在工作中可以做到的。vbhtml(如果您只需要使用Elmah日志记录错误,那么它可以工作)

@ModelType System.Web.Mvc.HandleErrorInfo

    @Code
        ViewData("Title") = "Error"
        Dim item As HandleErrorInfo = CType(Model, HandleErrorInfo)
        //To log error with Elmah
        Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(New Elmah.Error(Model.Exception, HttpContext.Current))
    End Code

<h2>
    Sorry, an error occurred while processing your request.<br />

    @item.ActionName<br />
    @item.ControllerName<br />
    @item.Exception.Message
</h2> 

It is simply!

这很简单!

#6


6  

A completely alternative solution is to not use the MVC HandleErrorAttribute, and instead rely on ASP.Net error handling, which Elmah is designed to work with.

一个完全替代的解决方案是不使用MVC HandleErrorAttribute,而是依赖于ASP。Net错误处理,这是Elmah设计用来处理的。

You need to remove the default global HandleErrorAttribute from App_Start\FilterConfig (or Global.asax), and then set up an error page in your Web.config:

您需要从App_Start\FilterConfig(或Global.asax)中删除默认的全局HandleErrorAttribute,然后在您的Web.config中设置一个错误页面。

<customErrors mode="RemoteOnly" defaultRedirect="~/error/" />

Note, this can be an MVC routed URL, so the above would redirect to the ErrorController.Index action when an error occurs.

注意,这可以是一个MVC路由URL,因此上面的内容将重定向到ErrorController。发生错误时的索引操作。

#7


5  

For me it was very important to get email logging working. After some time I discover that this need only 2 lines of code more in Atif example.

对我来说,让电子邮件记录工作起来很重要。经过一段时间,我发现在Atif示例中只需要2行代码。

public class HandleErrorWithElmahAttribute : HandleErrorAttribute
{
    static ElmahMVCMailModule error_mail_log = new ElmahMVCMailModule();

    public override void OnException(ExceptionContext context)
    {
        error_mail_log.Init(HttpContext.Current.ApplicationInstance);
        [...]
    }
    [...]
}

I hope this will help someone :)

我希望这能帮助一些人:

#8


2  

This is exactly what I needed for my MVC site configuration!

这正是我需要的MVC站点配置!

I added a little modification to the OnException method to handle multiple HandleErrorAttribute instances, as suggested by Atif Aziz:

我对OnException方法进行了一点修改,以处理多个HandleErrorAttribute实例,正如Atif Aziz所建议的:

bear in mind that you may have to take care that if multiple HandleErrorAttribute instances are in effect then duplicate logging does not occur.

请记住,如果多个HandleErrorAttribute实例生效,那么就不会发生重复日志记录。

I simply check context.ExceptionHandled before invoking the base class, just to know if someone else handled the exception before current handler.
It works for me and I post the code in case someone else needs it and to ask if anyone knows if I overlooked anything.

我只是检查上下文。在调用基类之前处理exceptionhandle,只需要知道是否有人在当前处理程序之前处理了这个异常。它适用于我,我发布代码,以防别人需要它,并询问是否有人知道我忽略了什么。

Hope it is useful:

希望它是有用的:

public override void OnException(ExceptionContext context)
{
    bool exceptionHandledByPreviousHandler = context.ExceptionHandled;

    base.OnException(context);

    Exception e = context.Exception;
    if (exceptionHandledByPreviousHandler
        || !context.ExceptionHandled  // if unhandled, will be logged anyhow
        || RaiseErrorSignal(e)        // prefer signaling, if possible
        || IsFiltered(context))       // filtered?
        return;

    LogException(e);
}