Exception handling beyond Exception Filters?

Using Asp.net WebApi (RC), how can I catch errors that are not caught by Exception Filters or Application_Error() in global.asax?

With both of these in place it seems that there is a class of exceptions still not covered. For example: ApiControllerActionSelector_AmbiguousMatch error (Multiple actions were found that match the request: {0}).

I’m not specifically concerned about the above error, this error just pointed out that there is a class of errors that aren’t being caught by either my Exception Filter or Application_Error method.

So how can I cover all my bases?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You’re right, there are several classes of exception not trapped by either Application_Error or ExceptionFilter. The Web API request pipeline is processed separately from the ASP.NET MVC pipeline (at least through MVC 4) so the MVC Application_Error doesn’t kick-in. Also, if your application throws HttpResponseException type exceptions, they will not be caught by an ExceptionFilter by design (see the ExceptionFilter paragraph). To access all exceptions thrown by your code, you’ll need to create a DelegatingHandler along the lines of this code:

public class ResponseExceptionTrapper : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        return base
            .SendAsync(request, cancellationToken)
            .ContinueWith(response =>
                 {
                     var result = response.Result;
                     if (!result.IsSuccessStatusCode)
                     {
                          var exceptionResult = string.Format(
                               "Response exception: Path({0}) Status({1}) ",
                               request.RequestUri,
                               result.StatusCode);

                          if (result.Content != null)
                          {
                               var exceptionReadTask =
                                      result.Content.ReadAsStringAsync();

                               exceptionReadTask.Wait();
                               exceptionResult += "Message:nr" +
                                                 exceptionReadTask.Result;
                           }

                           // Do something appropriate with exceptionResult
                      }

                      return result;
                 }, cancellationToken);
    }
}

You can wire up the handler with this line in your global config logic:

GlobalConfiguration.Configuration.MessageHandlers.Add(
     new ResponseExceptionTrapper());

Method 2

I believe that Exception Filters only get called once the action is invoked (in which case there is a try/catch around it). The Ambiguous match error would pop up before that in the pipeline and there could be other errors that pop up after that (e.g. a formatter error) as you mention.

I’m not sure you can have one solution to address all of the aspects (since the hosting implementation can vary), but you could try overriding the HttpControllerDispatcher. This class is one of the “root” classes used in the pipeline. Specifically, you could override SendAsync to do your try/catch and handle accordingly.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x