3

In the Web API that I'm working with, I have several conditions I'm checking for before I send JSON response to the calling program.

One way I have handled errors is to return something like this:

return Content(HttpStatusCode.NotFound, "This user reached maximum API calls for today.", new JsonMediaTypeFormatter(), "application/json");

When I tested the API using something like this:

var result = new System.Net.WebClient().DownloadString("BadURL");

I get an unhandled Exception error, which is expected.

To get around this, I change return statement in my error handling logic to something like this:

return Content(HttpStatusCode.OK, "This user reached maximum API calls for today.", new JsonMediaTypeFormatter(), "application/json");

So even the user uses the same WebClient() above, they get a useful error message (this and other error messages are well documented on the website) and no Exception.

Is this a good way of handling errors in ASP.NET Web API?

1
  • 1
    Looks ok to me although I'm not sure you want to return OK if there's a problem/error. Here's a list of HTTP status codes to choose from.
    – Rick S
    Commented Dec 20, 2016 at 16:18

2 Answers 2

1

I think you should probably make your API modeled around standard status codes. (You shouldn't return a 200 when there was an error).

Here are some common used status codes for REST API http://www.restapitutorial.com/httpstatuscodes.html

The issue you're seeing is just that WebClient throws exceptions on lots of status codes (404 for example). I don't think your api should revolve around making WebClient not throw exceptions. You can wrap the WebClient in try catch and grab the WebException and get the status code and error message from there.

(not tested code, but something similar to this)

try 
{
    var result = new System.Net.WebClient().DownloadString("BadURL");
    // process result
}
catch (WebException webEx)
{
    var statusCode = ((HttpWebResponse)webEx.Response).StatusCode;
    var body = new StreamReader(webEx.Response.GetResponseStream()).ReadToEnd();
    switch (statusCode) 
    {
        case 404:
           // parse error from your body (or in your case it is your body)
        case ...:
    }
}
1

You should probably look into proper HTTP responses for various situations. If I got a failed condition (api limit reached), I would expect to receive a 4xx error as that tells me not to retry the request. Maybe 402 or even 509. Some might argue that 403 is appropriate since it implies that your authentication was good, you're just not allowed to access the resource for whatever reason (authorization was removed due to exceeding the limit, for example)

That being said, you'll want to consider security of your API. Many APIs only return 2xx 400, and 500. The reason being is that you don't necessarily want to give too much information about the error. 400 tells me that my request is bad and I should stop trying, and 500 tells me that the server choked on something (not my problem). If you need to give more info away for developers to work against, consider using a custom message format that includes an application code and ensure there is developer documentation that explains the code.

For example:

400 response with body

{
  "code" : 8512,
  "message" : "account status"
}

This gives you both granularity and some level of obscurity. My client can now see that I should stop trying the request, but if the code is significant, I can use it to take action.

It's mentioned below that WebClient throws and you could catch it, check the code, and build an appropriate message. However, I'd recommend using HttpClient which only throws on non-success if you tell it to. And it's the more standard client to use.

What I've done in the past is to wrap my service responses in a formatter that has all of my response rules. So for example, I'll get the HttpResponseMessage back which I'll use as a ctor argument to the generic formatter. The formatter will basically expose the response content as well as translate the code, and put both into my standard response format that I can send back. That covers situations where my API is acting as a proxy to another web service. To cover cases where I just need to translate an exception (or other error), we just added to the map (the one that we put in the formatter) that has an Exception-to-Status code mapping. If you're interested in something like that, let me know and I'll try to recreate it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.