A demonstration of two patterns for structuring ASP.NET Core Minimal APIs using extension methods.
These are examples of common project structures with the goal of demonstrating how to define
minimal API endpoints without cluttering Program.cs
.
- Controller-style pattern: Defines endpoints in a way similar to MVC controllers by grouping related routes and handlers.
- REPR pattern: Follows the Request, Endpoint, Response structure for each resource, without external libraries.
This repository showcases three extension methods:
MapCustomerEndpoints
– MVC-like grouping for Customer endpoints.MapOrderEndpoints
– REPR pattern for Order endpoints.MapProductEndpoints
– REPR pattern for Product endpoints.
Watch the full walkthrough on YouTube:
- .NET 10 Preview 5 SDK or later
- Visual Studio 2022 preview / Visual Studio Code
-
Clone the repository:
git clone https://github.com/CoderFoundry/minimalAPIPatterns.git cd minimalAPIPatterns
-
Run the project:
cd minimalapistructure dotnet run
-
View the API Documentation by visiting https://localhost:7127/ in your browser
Defined in CustomerEndpoints.cs using the MapCustomerEndpoints
extension method:
public static class CustomerEndpoints
{
public static IEndpointRouteBuilder MapCustomerEndpoints(this IEndpointRouteBuilder route)
{
var group = route.MapGroup("/customers").WithTags("Customers");
group.MapGet("", GetCustomers);
group.MapGet("{id:int}", GetCustomerById);
group.MapPost("", CreateCustomer);
group.MapPut("{id:int}", UpdateCustomer);
group.MapDelete("{id:int}", DeleteCustomer);
return group;
}
// Handler methods (GetCustomers, GetCustomerById, etc.) live in the same file.
private static async Task<Ok<IEnumerable<CustomerResponse>>> GetCustomers(ICustomerService svc)
{
return TypedResults.Ok(
await svc.GetCustomersAsync()
);
}
// ...other methods below...
}
Defined in OrderEndpoints.cs using the MapOrderEndpoints
extension method:
public static class OrderEndpoints
{
public static IEndpointRouteBuilder MapOrderEndpoints(this IEndpointRouteBuilder route)
{
var group = route.MapGroup("/orders").WithTags("Orders");
group.MapGet("", GetOrdersHandler.Handle);
group.MapGet("{id:int}", GetOrderByIdHandler.Handle);
group.MapPost("", CreateOrderHandler.Handle);
group.MapPut("{id:int}", UpdateOrderHandler.Handle);
group.MapDelete("{id:int}", DeleteOrderHandler.Handle);
return group;
}
// Each endpoint has its own folder with its handler, request DTO, and response DTO
}
Each endpoint in the REPR pattern has its own folder for the endpoint, located in Endpoints/Orders.