2

I am building a ASP.NET Web Api service and I would like to create centralized exception handling code.

I want to handle different types of exceptions in different ways. I will log all exceptions using log4net. For some types of exceptions I will want to notify an administrator via email. For some types of exceptions I want to rethrow a friendlier exception that will be returned to the caller. For some types of exceptions I want to just continue processing from the controller.

But how do I do that? I am using an Exception Filter Attribute. I have this code working. The attribute is registered properly and the code is firing. I just want to know how I can continue if certain types of exceptions are thrown. Hope that makes sense.

public class MyExceptionHandlingAttribute : ExceptionFilterAttribute
{
  public override void OnException(HttpActionExecutedContext actionExecutedContext)
  {
    //Log all errors
    _log.Error(myException);

    if(myException is [one of the types I need to notify about])
    {
      ...send out notification email
    }

    if(myException is [one of the types that we continue processing])
    {
      ...don't do anything, return back to the caller and continue
      ...Not sure how to do this.  How do I basically not do anything here?
    }

    if(myException is [one of the types where we rethrow])
    {
      throw new HttpResponseException(new HttpResponseMessage(StatusCode.InternalServerError)
      {
        Content = new StringContent("Friendly message goes here."),
        ReasonPhrase = "Critical Exception"
      });
    }
  }
}
Rui Jarimba
  • 9,732
  • 10
  • 46
  • 74
Corey Burnett
  • 7,048
  • 9
  • 52
  • 87
  • The exception filters only get triggered in the "return" part of the WebAPI message pipeline. So, if you rely on an exception filter to handle your exceptions, I don't think there is an easy way to have the request re-enter the pipeline for further processing. See the [MVC Poster](http://www.asp.net/posters/web-api/ASP.NET-Web-API-Poster.pdf) for more information on the WebAPI extension points. – Marjan Venema Oct 29 '13 at 15:44

1 Answers1

2

For some types of exceptions I want to just continue processing from the controller. But how do I do that?

By writing try..catch where you want this behaviour to occur. See Resuming execution of code after exception is thrown and caught.

To clarify, I assume you have something like this:

void ProcessEntries(entries)
{
    foreach (var entry in entries)
    {
        ProcessEntry(entry);
    }
}

void ProcessEntry(entry)
{
    if (foo)
    {
        throw new EntryProcessingException();
    }
}

And when EntryProcessingException is thrown, you actually don't care and want to continue execution.


If this assumption is correct: you can't do that with a global exception filter, as once an exception is caught, there's no returning execution to where it was thrown. There is no On Error Resume Next in C#, especially not when the exceptions are handled using filters as @Marjan explained.

So, remove EntryProcessingException from your filter, and catch that specific exception by changing the loop body:

void ProcessEntries(entries)
{
    foreach (var entry in entries)
    {
        try
        {
            ProcessEntry(entry);
        }
        catch (EntryProcessingException ex)
        {
            // Log the exception
        }
    }
}

And your loop will happily spin to its end, but throw on all other exceptions where it will be handled by your filter.

Community
  • 1
  • 1
CodeCaster
  • 131,656
  • 19
  • 190
  • 236
  • A try except won't do as the Exception filter can be seen as a type of "application global exception catcher" and won't (easily) allow the message to be processed further, which seems to be what the OP is after. – Marjan Venema Oct 29 '13 at 15:45
  • @Marjan OP seems to want an "On Error Resume Next" for specific exceptions. You can't do that without a `try..catch` for that specific exception in that call site, because if you don't catch that exception but let it be handled by a filter, there's no turning back to where it was thrown. – CodeCaster Oct 29 '13 at 15:46
  • I know, but a try catch won't help for what he wants to do either: do all exception handling in a single location: the exception filter. The exception filter is triggered by the WebAPI framework, as a response to an exception thrown by "user code". – Marjan Venema Oct 29 '13 at 15:48
  • 1
    Yay. That's what I meant. Nice write up. – Marjan Venema Oct 29 '13 at 16:02
  • Thank you. That is a great explanation. I ended up doing exactly what you suggested in your last code block. – Corey Burnett Oct 29 '13 at 16:14