.net – Exception Handling ASP.NET MVC Web API

.netasp.net-mvcasp.net-web-apiiis-7

I'll start off with, yes, we have created and are using an exception filter inheriting from the ExceptionFilterAttribute. It is registered in the config on app startup right after our identity filter and works pretty much as expected if an error occurs somewhere inside our API.

That being said, I'm looking for a way to handle errors that happen before it reaches the API.

Reasoning: We never want to return a YSOD and/or IIS HTML error. We ALWAYS want to hit a custom exception filter/handler so that we can handle logging correctly and return a JSON response to the user.

As of right now, using Fiddler to make a request, I can attach to the w3wp.exe process and see the request hit the Application_BeginRequest method in the global.asax. After that, it just returns a 500 response. It never breaks in code with an exception or hits any of my break points after that. It seems to be returning an IIS error. We never want this to happen. We need the ability to catch all of these "low-level" exceptions, log them, and return something meaningful to the user.

Is there something we can do to handle errors before, what seems to be hitting the ASP.NET MVC Web API code?

Best Solution

Albeit I like Darin's answer it doesn't work in our case since the ASP.NET MVC Web API framework is suppressing/handling exceptions internally and not re-throwing to hit the Application_Error method in the Global.asax. Our solution is this.

I ended up creating a custom DelegatingHandler like so:

public class PrincipalHandler : DelegatingHandler
{
    protected const string PrincipalKey = "MS_UserPrincipal";
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        setAnonymousPrincipal();

        request = InitializeIdentity(request);

        return base.SendAsync(request, cancellationToken)
            .ContinueWith(r =>
                              {
                                  // inspect result for status code and handle accordingly
                                  return r.Result;
                              });
    }
}

I then inserted it into the HttpConfiguration to make sure it is the first/last handler to be hit. The way handlers work in the Web API is in a hierarchical fashion. So the first handler to be hit per request, will be the last handler to be hit on the response. At least this is my understanding, someone feel free to correct me if I'm wrong.

public static void ConfigureApis(HttpConfiguration config)
{
    config.MessageHandlers.Insert(0, new PrincipalHandler());
}

By using this approach we can now inspect every result coming back in any response from the web API and controllers. This allows us to handle any logging that may need to occur as a result of something not being returned as we expect. We can now also alter the content of the response coming back so that IIS doesn't insert any default HTML error pages if it sees certain HTTP status codes.

The only problem I have with this, and I'm hoping they change it in an upcoming release of the web API, is that they aren't sending the exception back up on the Task being returned from base.SendAsync(). So the only information we have to go by is the HTTP status code and try our best to give a reasonable or probable answer to the consumer.