Exercise: Northwind Web API

Build Northwind's products API. Write an async controller with GET (all, by category, by id), POST, PUT and DELETE, each answering the right status code, and set up Program.cs to register the DAO and handle errors in one place.

Journeyman · ASP.NET Core · REST API · Updated

Northwind's products need an API, so other programs, such as a mobile app or a web page's JavaScript, can read and change them. The model and the Dapper DAO are written. You'll write the controller, and set up Program.cs.

Get the exercise code

Open this lesson's GitHub repository, github.com/ask-codey/exercise-northwind-web-api, also linked from the Exercise box beside the lesson. Click Code, then Download ZIP, and unzip it into your bootcamp folder. Or clone it with Git. Then open NorthwindApi.slnx in Visual Studio.

File What's in it
NorthwindApi/Models/Product.cs A product, with its validation rules
NorthwindApi/Data/IProductDao.cs, ProductDao.cs The products table, with async Dapper methods
NorthwindApi/Errors/DatabaseConflictHandler.cs Answers SQL Server's constraint errors with 409 Conflict
NorthwindApi/Controllers/ProductsController.cs For you to finish. Its requirements are in the comment at the top.
NorthwindApi/Program.cs For you to finish, where the TODO comments are
NorthwindApi/NorthwindApi.http Ten numbered requests, each with the answer to expect
NorthwindApi.Tests Tests that start the API in memory, with a fake DAO

The API uses your own Northwind database. If yours has another name, change the connection string in appsettings.json.

What to do

Program.cs:

  1. Register ProductDao as the IProductDao, with the connection string.
  2. Add problem details, and register the DatabaseConflictHandler.
  3. Handle exceptions for the whole API.

ProductsController, every action async:

Request Answers
GET /api/products 200 with every product
GET /api/products?categoryId=1 200 with that category's products
GET /api/products/1 200 with the product, or 404
POST /api/products 201 with the new product and its address, or 400 for an invalid one
PUT /api/products/1 200 with the updated product, or 404
DELETE /api/products/1 204, or 404

Run the tests with Test > Run All Tests. Then run the API with Ctrl+F5, open NorthwindApi.http, and send its requests in order.

Hints

  • An optional filter from the query string is a nullable parameter: GetAll(int? categoryId). The DAO already knows what to do with null.
  • {id:int} in each route template matches whole numbers only.
  • CreatedAtAction(nameof(GetById), new { id = added.ProductId }, added) answers 201, with the Location header.
  • You don't need to check ModelState: [ApiController] answers 400 for an invalid product before your action runs.
  • The tests use a fake DAO with three products, swapped in for ProductDao. That works because the controller asks for an IProductDao, not a ProductDao: the interface from Abstraction and Interfaces paying off.
  • Product 666 makes the fake DAO throw. Your API should answer 500 problem details, without showing the exception's message.

When you're done

Every test passes, and the .http file's requests answer as their comments say. The last one is the best: deleting Chai, which orders still use, answers:

HTTP/1.1 409 Conflict
Content-Type: application/problem+json

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.10",
  "title": "Conflict",
  "status": 409,
  "detail": "Other data uses this item, or it uses data that doesn't exist, so it can't be saved or deleted."
}

A database error, turned into a clear answer, without a single try in your controller.

Submit your exercise

The exercise is how you finish this lesson. When your work is done, put it on GitHub in a repo of your own, then submit that repo's address here.

  1. On GitHub, click +, then New repository. Name it (for example exercise-northwind-web-api), choose Public, and click Create repository. Leave out the README: your folder already has one.

  2. In a terminal in your exercise folder (Git Bash on Windows), send your work to your new repo. If you downloaded the ZIP:

    git init -b main
    git add .
    git commit -m "My solution"
    git remote add origin https://github.com/your-name/exercise-northwind-web-api.git
    git push -u origin main
    

    If you cloned the starter instead, point your copy at your own repo, then commit and push:

    git remote set-url origin https://github.com/your-name/exercise-northwind-web-api.git
    git add .
    git commit -m "My solution"
    git push -u origin main
    
  3. Paste your repo's address, such as https://github.com/your-name/exercise-northwind-web-api, into Submit your exercise on this page. The site checks that the repo is public and holds your commits, and then the lesson is complete.

Changed something after you submitted? Push it, and submit again: your latest submission is the one that counts.

So what

That's a complete, professional API: REST addresses, honest status codes, async all the way down, validation for free, and errors handled in one place. The next chapter writes the other side: a C# program that calls it.

Key terms

Related