11

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?

4
  • This feels wrong somehow. Are you throwing exceptions in a library somewhere? Why not just catch the exception in the controller and return an error view of your own choosing? Commented Apr 23, 2012 at 16:48
  • 1
    This is using the ASP.NET MVC Web API, so we aren't returning views from controllers. We return JSON/XML responses. I also mention in my question that I need a way to handle exceptions BEFORE they reach the controllers. Right now we have an ExceptionFilter that catches exceptions anywhere once we are inside the controller so we don't have to have try/catches in every action.
    – jaryd
    Commented Apr 23, 2012 at 18:23
  • I don't think that I'm fully understanding your question. What types of errors are you trying to catch exactly? Commented Apr 23, 2012 at 19:05
  • 5
    @cecilphillip For instance if someone hits the service with a bad JSON format and the API can't find a formatter for it. Or someone hits a controller trying to use a GET when only a POST is there and it sends back a 405. Things that happen before it would get to a controller, which is what filters are for. It's almost as if there's an exception being thrown in the ControllerDispatcher or some kind of built in handler. I inserted a custom DelegatingHandler in the config to see the response coming back. I can see the InternalServerError message coming back in the debugger but not the exception.
    – jaryd
    Commented Apr 23, 2012 at 19:37

1 Answer 1

4

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.

3

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.