0
votes

I wanted a method which caught all unhandled exceptions in my asp.net web api project. I found this post: How do I log ALL exceptions globally for a C# MVC4 WebAPI app? which talks about using ExceptionFilterAttribute and OnException.

This is working so far, that i am able to catch an exception thrown in an api controller, and then identify the exception. I would then like to throw a HttpResponseException with StatusCode and Content specific to the original exception i caught. How would i do this?

This is what i have so far:

public override void OnException(HttpActionExecutedContext context) {
    HttpResponseMessage msg = new HttpResponseMessage();
    if (context.Exception.GetType() == typeof(DBAccess.DeleteNotAllowed)) {
        msg.StatusCode = HttpStatusCode.Forbidden;
        msg.Content = new StringContent("Illegal action");
        msg.ReasonPhrase = "Exception";
        throw new HttpResponseException(msg);
    } else {
        //handle next exception type
    }
}

When a DeleteNotAllowed exception is thrown it is caught as intended and it's error message is sent to the client. However, another exception is thrown at the else statement.

2

2 Answers

0
votes

The best approach is use Elmah.

It is one of the best tool that I have been using since 2010. It is the most useful tool for Exception handling. It will also give you a nice easy to use interface to view errors on web, e-amil and db.

for more details, please refer: http://blogs.msdn.com/b/webdev/archive/2012/11/16/capturing-unhandled-exceptions-in-asp-net-web-api-s-with-elmah.aspx

0
votes

As I understand, you want to translate all server side exceptions more human readable and meaningful ones? If this is what you want, then you have two options, write if/else or try/catch for all possible exception types, which will violate OCP - Open Closed Principle , instead of this I suggest you this approach: Let each exception decide it's own "translation" for client, catch them in OnException and return to the client message and status code given by concrete exception.

    public class ApiException : Exception
    {
        public int FaultCode { get; private set; }

        public ApiException(int faultCode, string message)
            : base(message)
        {
            this.FaultCode = faultCode;
        }
    }

As you see it has FaultCode and Message (inherited from base Exception) properties, with it's constructor you require from each concrete implementer of ApiException to pass it's own status code and message(those you will translate later in OnException method).

    public override void OnException(HttpActionExecutedContext context)
    {
        HttpResponseMessage msg = new HttpResponseMessage();

        if (context.Exception is ApiException)
        {
            ApiException apex = context.Exception as ApiException;

            msg.StatusCode = apex.StatusCode;
            msg.Content = new StringContent(apex.Message);
            throw new HttpResponseException(msg);
        }
    }

And that's what your OnException method should look like.