askill
minimal-api-organization

minimal-api-organizationSafety 95Repository

Expert in organizing ASP.NET Core Minimal APIs for production apps - extension methods, TypedResults, endpoint groups, testable handlers

0 stars
1.2k downloads
Updated 2/25/2026

Package Files

Loading files...
SKILL.md

What I Do

  • Organize minimal API endpoints into clean, maintainable structure
  • Replace inline lambdas with extension method registrations
  • Convert Results to TypedResults for compile-time safety and auto OpenAPI docs
  • Extract handlers into testable static methods
  • Group related endpoints with MapGroup for DRY configuration

When to Use Me

Trigger phrases:

  • "Add API endpoint"
  • "Organize minimal APIs"
  • "Create new endpoint group"
  • "Refactor Program.cs endpoints"
  • "Set up endpoint registration"
  • "Clean up API routes"
  • "Add endpoint for [resource]"

Use this skill when working with ASP.NET Core minimal API endpoints, restructuring Program.cs, or implementing new API routes in .NET projects.


Core Principles

1. Extension Methods for Endpoint Registration

Organize endpoints into separate files with extension methods.

File structure:

backend/Aimy.API/
├── Program.cs           # Clean entry point
└── Endpoints/
    ├── TodoEndpoints.cs
    └── UserEndpoints.cs

2. TypedResults Instead of Results

TypedResults provides:

  • Automatic OpenAPI/Swagger documentation (no .Produces() needed)
  • Compile-time type checking
  • Simpler unit testing

3. Separate Handlers from Registration

Extract lambda handlers into named static methods for testability and readability.

4. Group Related Endpoints

Use MapGroup to avoid route prefix repetition and apply shared configuration.


Implementation Pattern

// Endpoints/TodoEndpoints.cs
public static class TodoEndpoints
{
    public static void MapTodoEndpoints(this WebApplication app)
    {
        var todos = app.MapGroup("/todos")
            .WithTags("Todos")
            .RequireAuthorization();
        
        todos.MapGet("/", GetAllTodos);
        todos.MapGet("/{id}", GetTodoById);
        todos.MapPost("/", CreateTodo);
        todos.MapPut("/{id}", UpdateTodo);
        todos.MapDelete("/{id}", DeleteTodo);
    }
    
    static async Task<Ok<List<Todo>>> GetAllTodos(TodoDb db) =>
        TypedResults.Ok(await db.Todos.ToListAsync());
    
    static async Task<Results<Ok<Todo>, NotFound>> GetTodoById(int id, TodoDb db) =>
        await db.Todos.FindAsync(id) is Todo todo
            ? TypedResults.Ok(todo)
            : TypedResults.NotFound();
    
    static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb db)
    {
        db.Todos.Add(todo);
        await db.SaveChangesAsync();
        return TypedResults.Created($"/todos/{todo.Id}", todo);
    }
    
    static async Task<Results<NoContent, NotFound>> UpdateTodo(int id, Todo input, TodoDb db)
    {
        var todo = await db.Todos.FindAsync(id);
        if (todo is null) return TypedResults.NotFound();
        
        todo.Name = input.Name;
        todo.IsComplete = input.IsComplete;
        await db.SaveChangesAsync();
        return TypedResults.NoContent();
    }
    
    static async Task<Results<NoContent, NotFound>> DeleteTodo(int id, TodoDb db)
    {
        var todo = await db.Todos.FindAsync(id);
        if (todo is null) return TypedResults.NotFound();
        
        db.Todos.Remove(todo);
        await db.SaveChangesAsync();
        return TypedResults.NoContent();
    }
}

Clean Program.cs:

var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.Services.AddOpenApi();

var app = builder.Build();
app.UseHttpsRedirection();
app.MapDefaultEndpoints();

// One-line endpoint registrations
app.MapTodoEndpoints();
app.MapUserEndpoints();

app.Run();

TypedResults Reference

ResponseTypedResultUsage
200 + dataTask<Ok<T>>GET success
201 CreatedTask<Created<T>>POST create
204 No ContentTask<NoContent>PUT/DELETE
404NotFound in unionNot found
400BadRequest in unionValidation

Union pattern:

static async Task<Results<Ok<Todo>, NotFound, BadRequest>> GetTodo(int id, TodoDb db)
{
    if (id <= 0) return TypedResults.BadRequest();
    if (await db.Todos.FindAsync(id) is not Todo todo) 
        return TypedResults.NotFound();
    return TypedResults.Ok(todo);
}

Adding New Endpoints

  1. Create Endpoints/{Resource}Endpoints.cs
  2. Define Map{Resource}Endpoints(this WebApplication app)
  3. Create route group with app.MapGroup("/route")
  4. Add static handler methods with TypedResults
  5. Register in Program.cs: app.Map{Resource}Endpoints()

Anti-Patterns

AvoidProblemSolution
Inline lambdasUntestableExtension methods
ResultsNo type safetyTypedResults
Repeated prefixesDRY violationMapGroup
Business logic in handlersMixed concernsCore services

Testing

Test handlers directly without HTTP:

var result = await TodoEndpoints.GetTodoById(1, inMemoryDb);
Assert.IsType<Ok<Todo>>(result);

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

91/100Analyzed 2/19/2026

High-quality skill document for organizing ASP.NET Core Minimal APIs. Includes clear trigger phrases, comprehensive implementation patterns with full code examples, TypedResults reference table, step-by-step instructions, anti-patterns, and testing guidance. Well-structured with appropriate tags and organized in a dedicated skills folder. Technically accurate and highly actionable for developers working with minimal APIs.

95
90
90
92
88

Metadata

Licenseunknown
Version-
Updated2/25/2026
Publishererloon

Tags

apici-cdtesting