2

I am using Elmah and Elmah.mvc packages in a asp.net, mvc4 web app. I have a specific controller action where I want to handle HttpAntiForgeryExceptions in a specific manner. I have created a custom HandleErrorAttribute that inherits from HandleErrorAttribute and implements IExceptionFilter.

Under the specific circumstances I want to handle, I set the ExceptionContext.ExceptionHandled to true. The behaviour that the user sees is correct and the error is handled as I want it to be. However, it also logs an error to Elmah, which I don't want it to do, as I would like to keep the Elmah log for true errors.

The controller annotation looks like:

[ValidateAntiForgeryToken]
[CustomHandleAntiforgeryError]
public ActionResult ControllerMethod(Model model) 
{ 
    ... 
}

The CustomHandleAntiforgeryError looks like:

public class CustomHandleAntiforgeryErrorAttribute: 
                              HandleErrorAttribute, IExceptionFilter 
{
    public override void OnException(ExceptionContext filterContext)
    {
        if (circumstancesAreOk) 
        {
            filterContext.ExceptionHandled = true;
            return;
        }
    }
}

Is there anything else I need to do to prevent this error being logged with Elmah?

--- EDIT ---

Looking at the Elmah.MVC source the HandleErrorAttribute logs both handled and unhandled errors

public override void OnException(ExceptionContext context)
    {
        base.OnException(context);

        if (!context.ExceptionHandled) // if unhandled, will be logged anyhow
            return;

        var e = context.Exception;
        var httpContext = context.HttpContext.ApplicationInstance.Context;
        if (httpContext != null && 
            (RaiseErrorSignal(e, httpContext) // prefer signaling, if possible
             || IsFiltered(e, httpContext))) // filtered?
            return;

        LogException(e, httpContext);
    }

I would like a way within my custom attribute to signal to Elmah not to log this error and would appreciate any ideas.

AlexC
  • 10,676
  • 4
  • 37
  • 55
  • any luck with this one. by the looks of your EDIT above, Elmah returns out of the method if Exception is handled? – Christo Apr 09 '14 at 15:03
  • Described what I did, which works for me but is not a great solution to deal with a lot of problems. – AlexC Apr 11 '14 at 09:22

2 Answers2

0

See ErrorFiltering from Elmah's documentation. Here's the introduction:

When an unhandled exception is reported to ELMAH by ASP.NET, an application can decide whether to dismiss the exception or not. There are two ways for an application to do this, either programmatically or declaratively via the configuration file. The simpler of the two is programmatically because you do not need to learn anything new except write an event handler in your favorite language. The downside of the programmatic approach is that you need to write code and modify your web application (requiring possibly a static re-compile). With the configuration-based approach, you can simply apply filtering of exceptions to a running application.

mason
  • 31,774
  • 10
  • 77
  • 121
  • But this is about dealing with unhandled exceptions. However, even when I set the exceptionhandled to true elmah still logs the error. – AlexC Jan 03 '14 at 18:13
  • 1
    I have exactly same problem.. I searched complete app from all sides, I cannot find the point where elmah is logging handled exceptions – Lukas K May 20 '14 at 11:17
0

What I did to solve this I think is ugly, but worked for the weird error filter corner case that I was experiencing. I added a custom HandleErrorAttribute, copied from the Elmah HandleErrorAttribute and included a null check in the OnException method.

    public override void OnException(ExceptionContext context)
    {
        base.OnException(context);

        if (!context.ExceptionHandled) // if unhandled, will be logged anyhow
            return;

        string[] formKeys = context.HttpContext.Request.Form.AllKeys;

        var e = context.Exception;

        // linked to CustomErrorAttribute
        if (e == null)
        {
            return;
        }

        bool test = HostingEnvironment.IsHosted;

        var httpContext = context.HttpContext.ApplicationInstance.Context;
        if (httpContext != null &&
            (RaiseErrorSignal(e, httpContext) // prefer signaling, if possible
             || IsFiltered(e, httpContext))) // filtered?
            return;

        LogException(e, httpContext);
    }

Then, in my error filter, which I did not want to trigger messaging to Elmah, as well as setting the ExceptionContext ExceptionHandled to true I set the Exception to null

public class MyCustomErrorFilter : IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
         if (blah, blah, blah, weird things but not something terrible) 
         {
            filterContext.Exception = null;
            filterContext.ExceptionHandled = true;
            return;
         }
     }
 }

If it was something more involved and a regular occurrence I would probably fork Elmah and look at creating a custom Elmah build as this feels a little bit hacky to rely on in multiple situations.

AlexC
  • 10,676
  • 4
  • 37
  • 55