6

I am having a global Exception handler in my web api project. This works fine except when the exception is raised through a lambda expression. I have provided a sample code below:

[HttpGet]
public IHttpActionResult Test()
{
    //Throw new Exception();// this exception is handled by my ExceptionHandler
    var list = new List<int>();
    list.Add(1);
    IEnumerable<int> result = list.Select(a => GetData(a));
    return Ok(result);
}

private static int GetData(int a)
{
    throw new Exception();//This is not handled by my global exception handler
}

This is my global Exception Handler

public class ExceptionHandlerAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        //Do something
    }
}

I register it in my WebApiConfig class

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { action = "Get", id = RouteParameter.Optional }
        );
        config.Filters.Add(new ExceptionHandlerAttribute());
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Alborz
  • 6,843
  • 3
  • 22
  • 37

1 Answers1

1

The ExceptionFilterAttribute only works for exceptions thrown in your action method, see Exception Handling in ASP.NET Web API - Exception Filters. Your code will throw an exception during the materialization of the result, causing a SerializationException.

As explained in Global Error Handling in ASP.NET Web API 2:

Some unhandled exceptions can be processed via exception filters, but there are a number of cases that exception filters can’t handle. For example:

  • Exceptions thrown from controller constructors.
  • Exceptions thrown from message handlers.
  • Exceptions thrown during routing.
  • Exceptions thrown during response content serialization.

Register an exception handler or logger and act appropriately:

We provide two new user-replaceable services, IExceptionLogger and IExceptionHandler, to log and handle unhandled exceptions. The services are very similar, with two main differences: We support registering multiple exception loggers but only a single exception handler.

  1. Exception loggers always get called, even if we’re about to abort the connection.
  2. Exception handlers only get called when we’re still able to choose which response message to send.

See this answer in How do I log ALL exceptions globally for a C# MVC4 WebAPI app? for an implementation of both.

You can of course also materialize the enumerable in your controller, causing the exception to be thrown there and handled by the exception filter:

var result = list.Select(a => GetData(a)).ToList();
Community
  • 1
  • 1
CodeCaster
  • 147,647
  • 23
  • 218
  • 272