---
marp: true
paginate: true
math: mathjax
theme: buutti
title: 2. Controllers and HTTP Responses
---

# Controllers and HTTP responses

<!-- headingDivider: 5 -->
<!-- class: invert -->

## Controller-based API

* In the [previous Lecture 1](1-aspnet-introduction#an-example-controller-weathercontrollercs), we created a rudimentary ***controller-based web API*** in ASP.NET
  * See also [Create web APIs with ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-9.0)
  * ***Note:*** It's also possible to create [minimal APIs](https://learn.microsoft.com/en-us/aspnet/core/tutorials/min-web-api?view=aspnetcore-9.0&tabs=visual-studio) without controllers in ASP.NET
* Let's delve deeper into controllers that return HTTP responses with specific ***HTTP status codes***
  * For a primer on HTTP status codes, check [Frontend basics: Lecture 2](https://gitea.buutti.com/education/frontend-basics/src/branch/main/2-http.md#http-status-codes)

### Controllers

* Controllers are classes that derive from the [`ControllerBase`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase?view=aspnetcore-9.0) class
* In the project template, we had this controller:
  ```csharp
  [ApiController]
  [Route("[controller]")]
  public class WeatherForecastController : ControllerBase
  ```
* `ControllerBase` provides many properties and methods for handling HTTP requests
* Inside the class, we can create methods that correspond to different endpoints (see [Lecture 1: Routing and endpoints](1-aspnet-introduction#routing-and-endpoints))
  * These are called *__result methods__* 

### Result methods

* Result methods return `ActionResult` objects
  * For example, a `CreatedAtAction` returns the 201 status code
  * All `ActionResult` objects implement the `IActionResult` interface
  * Includes at least a status code, and can contain data such as view items or an error message
* This result is processed into a response to then sent to client
* There are multiple possible status codes for each action (See the following table)

#### Some result methods

| Status Code         | Result Method     | Usage                          |
|:-------------------|:-----------------|:----------------------------|
| `200 - OK`          | `Ok()`            | `GET`, `DELETE`              |
| `201 - Created`     | `Created()`       | `POST`                       |
| `204 - No content`  | `NoContent()`     | `PUT`, `PATCH`               |
| `400 - Bad request` | `BadRequest()`    | `POST`, `PUT`, `PATCH`       |
| `404 - Not found`   | `NotFound()`      | `All actions`                |
| `Custom`            | `StatusCode()`    | `All actions`                |

#### Result methods: An example

```csharp
[HttpGet("{id}")]
public IActionResult GetContactById(int id)
{
  // Contacts = list of contact objects, fetched from some repository
  var contact = Contacts.FirstOrDefault(c => c.Id == id);
  if (contact == null)
  {
    return NotFound();
  }
  return Ok(contact);
}
```

---

* The previous code first attempts to find a `Contacts` object using the ID provided in the URI parameter
  * If an item is not found, a 404 response is returned using `NotFound()`
![w:700](imgs/3-http-responses-and-status-codes_0.png) ➡ ![](imgs/3-http-responses-and-status-codes_1.png)
  * Otherwise, the object is sent as a payload with a 200 OK code response using `Ok(contact)`
![w:700](imgs/3-http-responses-and-status-codes_2.png) ➡ ![](imgs/3-http-responses-and-status-codes_3.png)

## Exercise 1: Returning status codes
<!--_class: "exercise invert" -->

1) Without using parameter constraints, modify your number list method from [Lecture 1, Exercise 3](1-aspnet-introduction#exercise-3-returning-your-own-list) to return a status code `400 (Bad Request)` if $k$ is smaller than $1$ or larger than $100$.
2) Add a helpful error message to the result for both cases. The message should be seen as a message body in the response.
3) Test with Swagger/Postman.

