Good morning everyone, and welcome to the new HTTP Status Codes in ASP.NET Web API tour here at Exception Not Found! My name is Reggie, and I'll be your tour guide today. Those of you who have taken our Exception Handling tour, welcome back! For those of you who are new to our facility, thank you for visiting us.

A guide leads a crowded tour of a museum. WikCon UK 2012 Science Museum tour 6 from Wikimedia, used under license

First off, I'd like to introduce my brilliant assistant Postman, who will be assisting me on this tour. Also assisting us will be Nathan, and he'll be doing whatever I need him to, and he better be grateful, this is his last chance, that little...

As I said, Nathan will be assisting us, since we have such a large group. This tour moves fast, so please keep up. Today, we're going to take a look around at the variety of status codes we can return from our Web API applications. Step right this way, stay together, and let's learn about what HTTP status codes are and how we use them in our ASP.NET Web API projects.

The Types of Status Codes

HTTP implements a wide variety of status codes, which are grouped into five categories. The five categories are distinguished by the code's first number, like so:

  • 1XX Codes: Informational codes. Rarely used in modern web apps.
  • 2XX Codes: Success codes. Tells the client that the request succeeded.
  • 3XX Codes: Redirect codes. Tells the client that they may need to redirect to another location.
  • 4XX Codes: Client Error codes. Tells the client that something was wrong with what it sent to the server.
  • 5XX Codes: Server Error codes. Tells the client that something went wrong on the server's side, so that the client may attempt the request again, possibly at a later time.

ASP.NET Web API can return any of those codes, though the more common ones have simpler return methods. Up next, we will show how we can determine what the proper code is to return from our action methods. This way, please.

Selecting the Proper Code

You should know that there is no "one true way" of selecting the proper status code; it all depends on your business rules. That said, unless your rules state otherwise, it is usually a good idea to return a more specific code rather than a more generic one.

As an example, consider a situation where your server needs to tell the client that a request that was submitted to it didn't have the proper authorization. One status code you could return is 400 Bad Request, as this implies that the request submitted was improper and not processed by the server. However, a more specific error code would be 401 Unauthorized, since that explicitly states what was wrong with the request. You should use more specific codes unless you have a business or security reason not to.

So, now we can start talking about what ASP.NET Web API does when it implements actions. If you'll just follow me to the next hallway, we can start to see code that shows what Web API will do in certain common situations.

Return Void - 204 No Content

Nathan, not that display case. Go to the other one. No, the other other one. YES THAT ONE.

Ahem! Take a look at the display case next to where Nathan is standing. Inside, we have one of our sample controllers:

public class MovieController : ApiController  
{
    [HttpPost]
    [Route("movies/add")]
    public void Add(string title, DateTime releaseDate, int runningTime)
    {
        Movie movie = new Movie()
        {
            Title = title,
            ReleaseDate = releaseDate,
            RunningTimeMinutes = runningTime
        };

        //Save movie to a data store
    }
}

You'll notice that this controller only has one action, which returns void. Postman, can you show us what the response looks like when we call this action please?

A Postman response, with the highlighted status code of 204 - No Content

When we call this action, we'll see that ASP.NET returns a status code of 204 - No Content. Since HTTP doesn't understand void, this is the appropriate status code. One of the many features we provide, at no extra charge!

But, what happens if we want to return something a little more complex? If you'll follow me right over here, we can see a sample.

Return Object - 200 OK

Nathan. NATHAN! Quit staring at that butterfly and get over here.

Excuse me. Now, take a look at this action:

[HttpGet]
[Route("movies/all")]
public List<Movie> GetAll()  
{
    List<Movie> movies = new List<Movie>()
    {
        new Movie()
        {
            Id = 1,
            Title = "Up",
            ReleaseDate = new DateTime(2009,5,29),
            RunningTimeMinutes = 96
        }
        //Create some other movies
    };

    return movies;
}

Now our action is returning an object. Postman, what kind of response do we get when calling this action?

A Postman response, with the highlighted code of 200 - OK

Now we get 200 - OK as the status code. But we didn't tell ASP.NET to return this code, so why did it?

Because if you return any serializable object from a Web API action, the response automatically becomes 200 - OK, with the object written in to the response body. Of course, if you wanted to explicitly specify that return code, all you would need to do is change the return type and return statement, like so:

[HttpGet]
[Route("movies/all")]
public IHttpActionResult PinkElephantsOnParade()  
{
    List<Movie> movies = new List<Movie>()
    {
        new Movie()
        {
            Id = 1,
            Title = "Up",
            ReleaseDate = new DateTime(2009,5,29),
            RunningTimeMinutes = 96
        }
        //Create some other movies
    };

    return Ok(movies);
}

Nathan you little animal I'm gonna....

Pardon the action name, we seem to have had a little... difficulty in setting up this display. Rest assured, whatever you name the action, you can use the shortcut method Ok() to return the status code 200 - OK.

Let's hurry along to the next display cabinet, where we will see some other shortcut methods we can use to represent commonly-returned status codes.

Shortcut Methods

I've been using the term "shortcut methods" to refer to a set of methods that return classes which implement IHttpActionResult. The next display cabinet has a few others, each of which represent common HTTP status codes:

  • BadRequest(): Returns 400 - Bad Request.
  • NotFound(): Returns 404 - Not Found.
  • InternalServerError(): Returns 500 - Internal Server Error.

There's also a catchall method, one that can return any HTTP status code:

  • StatusCode(HttpStatusCode statusCode): Returns the specified status code.

HttpStatusCode is an enumeration, whose values can be found over in the Status Codes exhibit. As you see at later points in this tour, HttpStatusCode becomes very useful when trying to return other, less common status from your API.

For now, let's continue down this hallway to see another method by which we can return status codes.

HttpResponseMessage

Though the shortcut methods are useful for common scenarios, they don't cover all possible status codes.... My apologies, please wait here a moment.

Nathan! Mrs. George does NOT need to be shown to the "bodily functions" display. No, it is not "interesting" or "transformative" it is gross and it doesn't even belong to this museum. Now come here! I swear, if your mother wasn't my sister...

As I was saying, the shortcut methods don't cover all possible status codes. For example, the red display in front of you has a method that should return 304 Not Modified:

[HttpGet]
[Route("movies/notmodified")]
public void NotModified()  
{
    //How do we return 304 Not Modified?
}

But there's no shortcut method for that return code, so how do we return it? We use HttpResponseMessage, like in the green display:

[HttpGet]
[Route("movies/notmodified")]
public void NotModified()  
{
    return new HttpResponseMessage(HttpStatusCode.NotModified);
}

HttpResponseMessage represents the response from the server to the client, and can be used with any of the status codes in the HttpStatusCode enumeration. In this way, we can return any of the standard status codes.

Nathan, that does not include 420, that's not a standard code and only one company uses it, stop changing the display!

HttpResponseMessage is perfect for returning status codes that aren't errors, but for the exception handling, there's a more appropriate solution: HttpResponseException.

HttpResponseException

Earlier, we talked about how it is important to select the appropriate status code when returning from an action in Web API projects. Consider the action in the next display:

[HttpGet]
[Route("movies/error")]
public void Error()  
{
    throw new NotImplementedException();
}

NotImplementedException is a .NET Exception that specifies that a given method is not implemented. However, HTTP does not understand .NET exceptions, so Web API will return an error code to a client that calls this method. The error code returned is 500 - Internal Server Error.

We like to say that returning 500 is the equivalent of the server throwing up its hands and saying "well, that didn't work." In other words, it's not a very useful status code. For situations where you don't want to give extra information to client (e.g. public-facing services that could be hit by malicious users) this may be exactly what you want. However, in many other scenarios there is a more appropriate status code to return: 501 Not Implemented.

We can do that by changing the action to look like this:

[Route("movies/error")]
[HttpGet]
public void Error()  
{
    throw new HttpResponseException(HttpStatusCode.NotImplemented);
}

HttpResponseException is a .NET class that translates to an HTTP status code. You can see how else we might handle exceptions with error codes on the Exception Handling tour.

Summary

In short, let's remember the following things about HTTP status codes in Web API projects:

  • Always return the appropriate status code, however you define "appropriate".
  • Use the shortcut methods (e.g. Ok(), NotFound(), etc.) when possible.
  • An action that returns void will send status code 204 No Content.
  • An action which returns an object will send 200 OK.
  • Use HttpResponseMessage for status codes that are not supported by shortcut methods.
  • Use HttpResponseException for error status codes.

Once again, thank you to Postman for your help on this tour (and go download it if you haven't already). For more information, see ASP.NET Web API 2: Building a Restful Service from Start to Finish by Jamie Kurtz and Brian Wortman, specifically Chapter 2, "What is RESTful?". You can find that in the bookshop, it's to your right on the way out of the building.

We hope you have a pleasant rest of your day, and please, come see us again!

Nathan! For the last time, get OUT of the restroom! I know you're not using it for its intended purpose, and the smell never comes out! Your mother will hear of this! You'll be sorry, young man!