Lesson 12 / 26

Routing and Model Binding

Read route values, query strings and JSON bodies and return proper status codes.

Where values come from

Handler parameters are bound automatically: names in {braces} come from the route, simple types from the query string, and a complex type from the JSON body. Results.* helpers set the status code.

GET by id and POST

TypedResults.NotFound() gives a 404 and TypedResults.Created gives a 201 with a Location header.

var products = new List<Product>();

app.MapGet("/products/{id:int}", (int id) =>
    products.FirstOrDefault(p => p.Id == id) is { } p
        ? Results.Ok(p)
        : Results.NotFound());

app.MapPost("/products", (Product p) =>
{
    products.Add(p);
    return Results.Created($"/products/{p.Id}", p);
});

record Product(int Id, string Name);

Use route constraints

{id:int} makes /products/abc fail to match, so you get a 404 instead of a conversion error inside your handler. Group related routes with app.MapGroup("/products").

Quick check: Which status code should a successful POST that creates a resource return?

  • 200 OK only
  • 204 No Content
  • 404 Not Found
  • 201 Created
Answer

201 Created — 201 signals that a new resource exists, ideally with a Location header pointing to it.