Recipe Catalog Web API
Build a recipe catalog API with ASP.NET Core and Entity Framework Core, stored in SQLite. It manages recipes with their ingredients, steps and tags, and supports searching by tag or ingredient and paging through results. Input is validated, errors come back in a consistent format, and integration tests prove the API works end to end. You'll learn ASP.NET Core controllers and routing, Entity Framework Core relationships (a recipe has many ingredients; recipes and tags are many-to-many) and migrations, returning the right status codes, DTOs that keep your database model separate from what the API exposes, and testing with WebApplicationFactory.
- Estimate
- ~11h
- Steps
- 6
- Completed by
- 0
- Proposed by
- codeseed.app
ASP.NET Core · Entity Framework Core · SQLite
Project roadmap
- 01
Create the project and models
~1.5hCreate an ASP.NET Core Web API project (.NET 8 or newer) with controllers. Define the entities Recipe (id, title, description, servings, prep minutes, steps as text), Ingredient (id, recipe id, name, quantity, unit) and Tag (id, unique name), where a recipe has many ingredients and recipes and tags are linked many-to-many. Done when: the project builds with the entity classes.
- 02
Set up EF Core with SQLite
~1.5hAdd Microsoft.EntityFrameworkCore.Sqlite and the design package. Create a RecipesDbContext, configure the relationships and a unique index on the tag name, and set the connection string in appsettings.json. Create the first migration and apply it with dotnet ef database update. Seed about 10 recipes with tags. Done when: the database file is created with the seeded recipes.
- 03
Implement the CRUD endpoints
~2.5hCreate a RecipesController with GET /api/recipes/{id}, POST, PUT and DELETE. Use DTOs for requests and responses (for example RecipeDto and CreateRecipeRequest) instead of returning entities directly, which avoids exposing internal fields and loops in JSON. Load ingredients and tags with Include. Return 201 with a Location header on create, 404 when not found and 204 on delete. Done when: all endpoints work in Swagger with the right status codes.
- 04
Add filtering and pagination
~2hMake GET /api/recipes accept ?tag=, ?ingredient= (matching part of an ingredient name), ?maxPrepMinutes=, ?page= and ?pageSize= (default 10, maximum 50). Build the query with IQueryable so filtering and paging happen in SQL, order by title, and return the items with totalCount, page and pageSize. Done when: filtering and paging return the right recipes, and the SQL logs show filtering in the database.
- 05
Validate input and handle errors
~1.5hAdd data annotations to the request DTOs (title required, 3 to 100 characters; servings 1 to 50; at least one ingredient), so invalid requests automatically return 400 with ProblemDetails. Add a global exception handler (UseExceptionHandler) that turns unexpected errors into a 500 ProblemDetails without a stack trace. Done when: invalid input gets clear 400 responses, and a forced error returns a clean 500.
- 06
Write integration tests
~2hCreate an xUnit test project using WebApplicationFactory, replacing the database with a SQLite in-memory connection that is kept open for the test. Test creating a recipe, getting it back with its ingredients and tags, filtering by tag, paging, validation errors and deleting. Done when: dotnet test passes.
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack