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.
Free plan: 30 tutor messages. PRO is unlimited.
