Minimal APIs + EF Core: a clean .NET 8 API
Program.cs .
Split with route groups
app.MapGet calls in Program.cs . The fix is one word: `MapGroup` . Each resource gets its own group, with its prefix, filters and metadata, defined in a dedicated extension method:
Program.cs then boils down to app.MapTodos(); — one entry point per resource, everything else lives in cohesive files.
DbContext and migrations
DbContext via AddDbContext , model in OnModelCreating , and above all never let the schema drift by hand: every change goes through a versioned migration.
dotnet ef migrations add InitialCreate , and apply it on startup with db.Database.MigrateAsync() — never EnsureCreated , which short-circuits the whole history. The official docs cover the workflow in the EF Core migrations guide .
Typed results and validation
IActionResult , you return a typed results union : the signature documents the possible HTTP codes, and OpenAPI exposes them automatically.
Results<Created<Todo>, ValidationProblem> is self-documenting : no need for redundant [ProducesResponseType] attributes.
Keeping it testable
AppDbContext on the in-memory or SQLite provider, call the handler, and inspect the TypedResults . For end-to-end integration tests, WebApplicationFactory<T> spins up the full application in memory and lets you hit the real endpoints.
A Minimal API isn't a budget API. Well split into groups and typed results, it exposes less ceremony for more guarantees — which is exactly what you want from a modern framework.