Start learning free

LESSON 21 OF 173 · BACKEND: YOUR FIRST API

Check the Input

Practice

A client can send anything: no name, a price written as text, a negative number. Never trust input. Before you store something, check it, and if it's wrong, answer 400 Bad Request with an error that tells the client what to fix. A 400 says the client made a mistake; a 500 says your server broke.

To read a key that may be missing, use TryGetProperty: data.GetProperty("color") throws when there is no "color", but data.TryGetProperty("color", out var colorValue) gives false. A value's ValueKind tells a number from text, and TryGetInt32(out var n) gives true only for a whole number, which it puts in n. Here is the idea on another route:

app.MapPost("/ratings", (JsonElement data) => {
    data.TryGetProperty("stars", out var starsValue);
    if (starsValue.ValueKind != JsonValueKind.Number || !starsValue.TryGetInt32(out var stars) || stars < 1 || stars > 5) {
        return Results.Json(new { error = "Stars must be a whole number from 1 to 5" }, statusCode: 400);
    }
    return Results.Json(new { stars = stars }, statusCode: 201);
});

A return ends the function, so a refused product is never stored. Your code must give, in this order:

POST /products  {"price": 5, "category": "home"}  →  400  {"error": "Name is required"}
POST /products  {"name": "", "price": 5, "category": "home"}  →  400  {"error": "Name is required"}
POST /products  {"name": "Cup", "category": "kitchen"}  →  400  {"error": "Price must be a whole number of 0 or more"}
POST /products  {"name": "Cup", "price": "5", "category": "kitchen"}  →  400  the same price error
POST /products  {"name": "Cup", "price": -1, "category": "kitchen"}  →  400  the same price error
POST /products  {"name": "Cup", "price": 4.5, "category": "kitchen"}  →  400  the same price error
POST /products  {"name": "Sticker", "price": 0, "category": "office"}  →  201  {"id": 5, "name": "Sticker", "price": 0, "category": "office"}
GET /products/count  →  200  {"count": 5}

Your task: in the POST route, read the name and the price with TryGetProperty, answer 400 with the right error when the name is missing or empty or the price isn't a whole number of 0 or more, and build the new product from the values you checked.


Assignment
Follow the Coding Tutorial to add the name check and the price check to the POST route for /products.


Hint
Each check is an if with ||, and a return inside it. In the price check, write the ValueKind check first, so TryGetInt32 never runs on text or a missing price. The starting code doesn't compile until the last step brings the newProduct line back.


STEP 1 OF 7
    Ctrl + Enter to check