HTTP Status Codes: an overview
Every response starts with a status code that says how the request went. By default an ASP.NET Core API answers 200 when an action returns, and 500 when it throws, so an action has to choose a better code, such as 404, on purpose.
Apprentice · REST API · ASP.NET Core · Updated
After this lesson you can
- Explain what an API's status code tells the client, and why a missing item should answer 404, not 200 or 204
Key takeaways
- A status code's first digit gives its family: 2xx means success, 4xx the client's mistake and 5xx the server's.
- By default ASP.NET Core answers
200 OKwhen an action returns, and500 Internal Server Errorwhen it throws an exception nobody catches. - An action that returns
nullanswers204 No Content, which tells the client everything went fine. - A missing item should answer
404 Not Found, not200or204, and your action has to choose that code on purpose. - Clients decide what to do from the status code alone, so it has to be right.
Every response starts with a status code: a three-digit number that tells the client how its request went, before it reads a single byte of the body.
HTTP/1.1 200 OK
The first digit gives the family:
| Codes | Mean | Whose problem |
|---|---|---|
| 2xx | Success | Nobody's: it worked |
| 4xx | Client error | The client's: a bad request, a wrong address, not signed in |
| 5xx | Server error | The server's: something broke on our side |
The client's code decides what to do from the status code alone: show the data, show "not found", ask the user to fix the form, or say "try again later". So the code has to be right.
What ASP.NET Core does by default
When an API action returns, ASP.NET Core answers 200 OK with what it returned as the body. When an action throws an exception that nobody catches, it answers 500 Internal Server Error. That's a sensible start, but look what happens with a category that doesn't exist:
[HttpGet("{id}")]
public Category? GetById(int id)
{
return categoryDao.GetById(id);
}
GET {{HostAddress}}/api/categories/300
HTTP/1.1 204 No Content
There's no category 300, so the DAO returned null, and ASP.NET Core answered 204 No Content: "it worked, and there's nothing to send." But it didn't work. The client asked for something that isn't there, and the honest answer is 404 Not Found.
A client reading 204 would think everything is fine, and show an empty page. One reading 404 knows to say "there's no such category".
Choosing the code on purpose
So an action has to decide its own status code whenever "it returned" isn't the whole story:
| The request | The right answer |
|---|---|
| Get a category that exists | 200 OK, with the category |
| Get a category that doesn't exist | 404 Not Found |
| Add a category | 201 Created, with the new category and its address |
| Add a category with no name | 400 Bad Request, saying what's wrong |
| Update a category | 200 OK, with the category as it's now saved |
| Delete a category | 204 No Content |
| The database is down | 500 Internal Server Error, without the details |
The next lesson lists the common codes, and Web APIs with Controllers shows how an action returns each one.
Check yourself
1 question to try on the lesson page.
So what
The status code is the first thing a client reads, and often the only thing it checks. ASP.NET Core picks 200 or 500 for you; every other answer, such as 404 for something that isn't there, is a choice you make in the action.