DELETE
DELETE removes the item at an address. It sends no body; the action deletes by the id from the route and answers 204 No Content, or 404 Not Found when there was nothing to delete.
Journeyman · ASP.NET Core · REST API · Updated
After this lesson you can
- Write a DELETE action that removes an item and answers 204 No Content, or 404 Not Found when it isn't there
Key takeaways
- A
DELETEto an item's address removes it. It sends no body: the id comes from the route. - The DAO returns
rows == 1, and the action answers204 No Content, or404 Not Foundwhen there was nothing to delete. - Deleting a category that still has products breaks a foreign key, and the uncaught
SqlExceptionsends the client a500with the stack trace. - Errors like that are best handled once, for the whole API, not in each action.
A client deletes an item with a DELETE to that item's address. Like a GET, it has no body: the address says which item.
The DAO
public bool Delete(int categoryId)
{
using SqlConnection connection = new SqlConnection(connectionString);
int rows = connection.Execute("DELETE FROM Categories WHERE CategoryId = @CategoryId;", new { CategoryId = categoryId });
return rows == 1;
}
Dapper's Execute returns how many rows the statement changed, so the number of rows tells you whether there was anything to delete. Unlike Update, there's nothing to hand back: the row is gone.
The action
[HttpDelete("{id}")]
public IActionResult Delete(int id)
{
if (!categoryDao.Delete(id))
{
return NotFound();
}
return NoContent();
}
DELETE {{HostAddress}}/api/categories/9
HTTP/1.1 204 No Content
Send the same request again, and it answers 404 Not Found: category 9 is already gone.
When the database says no
Now try deleting a category that has products:
DELETE {{HostAddress}}/api/categories/1
HTTP/1.1 500 Internal Server Error
Microsoft.Data.SqlClient.SqlException (0x80131904): The DELETE statement conflicted with the REFERENCE constraint "FK_Products_Categories". ...
Beverages has products, and the foreign key from Database Design in SQL Server won't let its category go. The DAO throws a SqlException, nobody catches it, and the client gets a 500 with the full error and stack trace.
That's fine while you develop: you see exactly what broke. But a real client should never see your stack trace, and a foreign-key conflict isn't really a server crash. Handling Global Exceptions in ASP.NET Core shows how to answer with something better, in one place for the whole API.
The full controller
With GET, POST, PUT and DELETE, the categories API is complete: five endpoints, all CRUD, in one class.
| Request | Action | Answers |
|---|---|---|
GET /api/categories |
GetAll() |
200 with the list |
GET /api/categories/8 |
GetById(8) |
200 with the category |
POST /api/categories |
Add(category) |
201 with the new category and its address |
PUT /api/categories/8 |
Update(8, category) |
200 with the updated category, or 404 |
DELETE /api/categories/8 |
Delete(8) |
204, or 404 |
Check yourself
1 question to try on the lesson page.
So what
DELETE is the simplest action: an id in, a status out. The interesting part is what happens when the database refuses, and that's a job for the whole API, not one action.