Organization by feature: each use case keeps its endpoint, request, validation, handler and data access together.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | // ====================================================================== // Q: What is Vertical Slice Architecture? // // Organization by feature: each use case keeps its endpoint, request, // validation, handler and data access together. A change touches one place, not // five layers. // - Each slice chooses its own complexity: a simple query goes straight to the // DbContext, a complex command goes through the domain model. // - Risk: duplicated rules. Shared business rules belong in the domain, not in // every slice. // - It combines well with Clean Architecture: the Domain / Infrastructure // boundaries stay, and inside Application the code is organized by feature. // ====================================================================== // Feature folder layout and a GetOrderById slice Features/ Orders/ CreateOrder.cs // request + validator + handler + endpoint CancelOrder.cs GetOrderById.cs Catalog/ SearchProducts.cs public static class GetOrderById { public record Response(int Id, string Number, decimal Total); public static void Map(IEndpointRouteBuilder app) => app.MapGet("/orders/{id:int}", Handle).RequireAuthorization(); private static async Task<Results<Ok<Response>, NotFound>> Handle( int id, AppDbContext db, CancellationToken ct) { var dto = await db.Orders.AsNoTracking() .Where(o => o.Id == id) .Select(o => new Response(o.Id, o.OrderNumber, o.TotalNet)) .FirstOrDefaultAsync(ct); return dto is null ? TypedResults.NotFound() : TypedResults.Ok(dto); } } |