A shop owner likes a quick summary of the shop: how many products it has, the lowest and the highest price, and the average price. None of these numbers is stored. Your route works them out from the products on every request, so they always match the shop.
All four come from the list of prices, and a C# list has a method for each part: Count counts the items, Min() and Max() find the smallest and the largest, and Average() adds them up and divides by the count. Math.Round(x, 2) keeps 2 decimal places. The same methods on other numbers:
var ages = new List<int> { 30, 25, 40 };
Console.WriteLine($"{ages.Count} {ages.Min()} {ages.Max()}"); // 3 25 40
Console.WriteLine(Math.Round(ages.Average(), 2)); // 31.67
An empty list has no average: Average(), Min() and Max() throw an InvalidOperationException on it, and the route crashes with a 500. So when the shop has no products, answer the count 0 and null for the other three. An anonymous object needs a typed null, like (int?)null, and Results.Json sends it as JSON's null, which means "no value".
Your code must answer these requests, in this order. A whole average like 45.0 is written as 45 in the JSON:
GET /stats → 200 {"count": 4, "cheapest": 2, "most_expensive": 29, "average_price": 12.5}
DELETE /products/1 → 204
GET /stats → 200 {"count": 3, "cheapest": 2, "most_expensive": 29, "average_price": 12.67}
DELETE /products/2, then /products/3, then /products/4 → 204 each
GET /stats → 200 {"count": 0, "cheapest": null, "most_expensive": null, "average_price": null}
POST /products {"name": "Chair", "price": 45, "category": "furniture"} → 201
GET /stats → 200 {"count": 1, "cheapest": 45, "most_expensive": 45, "average_price": 45}
Your task: add a MapGet route for /stats that answers count, cheapest, most_expensive and average_price (rounded to 2 places), with null for the last three when the shop is empty.
Assignment
Follow the Coding Tutorial to build the GET /stats route: collect the prices, handle an empty shop, work out the average, and answer the four keys.
Hint
Check for an empty list right after the loop, before you call Average(). Math.Round takes the number first and the number of places second. A lambda must return a value on every path, so the code compiles again only once the last return is in.
Free plan: 30 tutor messages. PRO is unlimited.
