Well, you can have partial Program class:
partial class Program
{
static IEndpointRouteBuilder MapProductEndpoints(IEndpointRouteBuilder endpoints)
{
endpoints.MapGet("/products/{id}", (int id) => Results.Ok());
return endpoints;
}
}
var app = builder.Build();
MapProductEndpoints(app);
or you can have static class or an extension method:
public static class ProductEndpoints
{
public static IEndpointRouteBuilder Map(IEndpointRouteBuilder endpoints)
{
endpoints.MapGet("/products/{id}", (int id) => Results.Ok());
return endpoints;
}
}
var app = builder.Build();
ProductEndpoints.Map(app);
public static class EndpointRouteBuilderProductEndpointsExtensions
{
public static IEndpointRouteBuilder MapProductEndpoints(this IEndpointRouteBuilder endpoints)
{
endpoints.MapGet("/products/{id}", (int id) => Results.Ok());
return endpoints;
}
}
var app = builder.Build();
app.MapProductEndpoints();
or you can wrap it in an interface and do assembly scanning or a source generator:
public interface IEndpoints
{
static IEndpointRouteBuilder Map(IEndpointRouteBuilder endpoints);
}
public class ProductEndpoints : IEndpoints
{
public static IEndpointRouteBuilder Map(IEndpointRouteBuilder endpoints)
{
endpoints.MapGet("/products/{id}", (int id) => Results.Ok());
return endpoints;
}
}
var app = builder.Build();
var assembly = Assembly.GetExecutingAssembly();
var endpointsCollection = assembly
.GetTypes()
.Where(type => !type.IsInterface && type.GetInterfaces().Contains(typeof(IEndpoints)));
foreach (var endpoints in endpointsCollection)
{
var map = endpoints.GetMethod(nameof(IEndpoints.Map));
map.Invoke(null, new[] { app });
}
https://dev.to/joaofbantunes/mapping-aspnet-core-minimal-api-endpoints-with-c-source-generators-3faj.
You can also try to do endpoint per file though that's trickier to enforce😅.