Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get ELMAH to work with ASP.NET MVC [HandleError] attribute?

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.

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.

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..

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....

like image 749
dswatik Avatar asked Apr 20 '09 02:04

dswatik


People also ask

How can use HandleError attribute in MVC?

Add HandleError Attribute on About Action method of HomeController. Add shared folder in Views and then add an Error View (error. cshtml), which will be shown when an exception is thrown. We can also declare HandleError attribute on the Controller level as well as on Action method.

How do you check Elmah error?

Build the application, run it in the browser, and navigate to http://www.yoursite.com/elmah.axd. You are prompted to log in before you see the content. After a successful authentication, you see a web page to remotely view the entire log of recorded exceptions.

What is Elmah logging?

ELMAH is a free, open source error logging library that includes features like error filtering and the ability to view the error log from a web page, as an RSS feed, or to download it as a comma-delimited file.


2 Answers

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:

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):

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.

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.

like image 116
Atif Aziz Avatar answered Oct 02 '22 13:10

Atif Aziz


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:

public static void RegisterGlobalFilters (GlobalFilterCollection filters) {     filters.Add(new ElmahHandledErrorLoggerFilter());     filters.Add(new HandleErrorAttribute()); } 
like image 42
Ivan Zlatev Avatar answered Oct 02 '22 12:10

Ivan Zlatev