dotnet-minimal-apis

NotMyself's avatarfrom NotMyself

Guide for building ASP.NET Core Minimal APIs with OpenAPI/Swagger integration in .NET 10

⭐5stars🔀0forks📁View on GitHub🕐Updated Nov 3, 2025⬇️1downloads

When & Why to Use This Skill

This Claude skill provides comprehensive guidance and optimized code patterns for building high-performance ASP.NET Core Minimal APIs using .NET 10. It streamlines the development of lightweight HTTP services by offering expert-level best practices for OpenAPI (Swagger) integration, efficient route grouping, and advanced parameter binding, enabling developers to build scalable, cloud-native microservices with significantly reduced boilerplate code.

Use Cases

  • Rapid Prototyping: Quickly scaffold and deploy lightweight RESTful microservices using the latest .NET 10 Minimal API features.
  • API Documentation: Automatically integrate and configure OpenAPI/Swagger to generate interactive documentation and client SDKs for web services.
  • Architecture Modernization: Refactor legacy controller-based ASP.NET Core applications into modern, high-performance Minimal API structures for better resource efficiency.
  • Standardized Development: Implementing consistent route groups, filters, and typed results across large-scale enterprise API projects to ensure maintainability.
  • Performance Optimization: Leveraging the lower overhead of Minimal APIs for high-throughput cloud-native applications and serverless functions.
namedotnet-minimal-apis
descriptionGuide for building ASP.NET Core Minimal APIs with OpenAPI/Swagger integration in .NET 10
typedomain
enforcementsuggest
prioritymedium

ASP.NET Core Minimal APIs

This skill provides guidance for building Minimal APIs in ASP.NET Core .NET 10. Minimal APIs provide a simplified approach to building HTTP APIs with minimal dependencies and boilerplate.

Table of Contents

  1. Overview
  2. Project Structure
  3. Basic Endpoints
  4. Route Groups
  5. Parameter Binding
  6. OpenAPI Integration
  7. Best Practices
  8. Quick Reference

Overview

What are Minimal APIs?

Minimal APIs are a simplified way to create HTTP APIs in ASP.NET Core without controllers. They provide:

  • Less code: No controllers, no attribute routing
  • Fast development: Define endpoints inline
  • Performance: Lower overhead than MVC controllers
  • Ideal for: Microservices, simple APIs, cloud-native apps

When to Use Minimal APIs

Use Minimal APIs when:

  • Building microservices
  • Creating simple REST APIs
  • Prototyping quickly
  • Prioritizing performance

Use MVC Controllers when:

  • Complex validation logic
  • Heavy use of filters/middleware per endpoint
  • Team prefers OOP patterns
  • Large enterprise applications

Project Structure

ClaudeStack.API Project

This repository includes src/ClaudeStack.API demonstrating minimal API patterns.

Current Program.cs structure:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = WebApplication.CreateBuilder(args);

// Add services
builder.Services.AddOpenApi();

var app = builder.Build();

// Configure middleware
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseHttpsRedirection();

// Define endpoints
app.MapGet("/weatherforecast", () => { /* ... */ })
   .WithName("GetWeatherForecast");

app.Run();

Key components:

  1. WebApplication.CreateBuilder(args) - creates builder
  2. builder.Services - dependency injection
  3. app.Build() - builds application
  4. app.Map*() - defines endpoints
  5. app.Run() - starts server

Basic Endpoints

MapGet

Simple GET endpoint:

app.MapGet("/hello", () => "Hello World!");

With route parameters:

app.MapGet("/users/{id}", (int id) => $"User {id}");

With query parameters:

app.MapGet("/search", (string? query) => $"Searching for: {query}");

Async with return type:

app.MapGet("/users/{id}", async (int id, UserService service) =>
{
    var user = await service.GetUserAsync(id);
    return user is not null ? Results.Ok(user) : Results.NotFound();
});

MapPost, MapPut, MapDelete

app.MapPost("/users", (User user) => Results.Created($"/users/{user.Id}", user));
app.MapPut("/users/{id}", (int id, User user) => Results.NoContent());
app.MapDelete("/users/{id}", (int id) => Results.NoContent());

Example from Project

From src/ClaudeStack.API/Program.cs:

app.MapGet("/weatherforecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast");

Key points:

  • Inline lambda
  • Returns typed data (serialized as JSON)
  • .WithName() for OpenAPI

Route Groups

Basic Route Group

Organize related endpoints:

var users = app.MapGroup("/users");

users.MapGet("/", () => "All users");
users.MapGet("/{id}", (int id) => $"User {id}");
users.MapPost("/", (User user) => Results.Created($"/users/{user.Id}", user));

Route Group with Prefix

var api = app.MapGroup("/api/v1");

api.MapGet("/users", () => "All users");
api.MapGet("/products", () => "All products");

Route Group with Filters

var admin = app.MapGroup("/admin")
    .RequireAuthorization("AdminPolicy");

admin.MapGet("/users", () => "Admin: All users");
admin.MapDelete("/users/{id}", (int id) => Results.NoContent());

Parameter Binding

Binding Examples

// Route parameters
app.MapGet("/users/{id}", (int id) => $"User {id}");

// Query string
app.MapGet("/search", (string? q, int page = 1) => $"{q}, Page {page}");

// Request body (JSON)
app.MapPost("/users", (User user) => Results.Created($"/users/{user.Id}", user));

// Dependency injection
app.MapGet("/users", (UserService service) => service.GetAllUsers());
// Register: builder.Services.AddScoped<UserService>();

// Multiple sources
app.MapPost("/users/{id}", (int id, User user, UserService service) =>
    service.UpdateUser(id, user));

OpenAPI Integration

Adding OpenAPI

This project uses OpenAPI (configured in Program.cs):

// Add service
builder.Services.AddOpenApi();

// Map OpenAPI endpoint (development only)
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

Access OpenAPI spec: https://localhost:5001/openapi/v1.json

Endpoint Metadata

Naming endpoints:

app.MapGet("/users", () => "All users")
   .WithName("GetAllUsers");

Adding descriptions:

app.MapGet("/users/{id}", (int id) => $"User {id}")
   .WithName("GetUser")
   .WithSummary("Get user by ID")
   .WithDescription("Returns a single user by their unique identifier");

Adding tags:

app.MapGet("/users", () => "All users")
   .WithTags("Users");

app.MapGet("/products", () => "All products")
   .WithTags("Products");

Response Types

app.MapGet("/users/{id}", (int id) => Results.Ok(new User()))
   .Produces<User>(StatusCodes.Status200OK)
   .Produces(StatusCodes.Status404NotFound);

Best Practices

1. Use Typed Results

Prefer:

app.MapGet("/users/{id}", (int id) =>
    Results.Ok(user)
    // or Results.NotFound()
);

Avoid:

app.MapGet("/users/{id}", (int id) => user); // Implicit 200 OK

2. Name All Endpoints

app.MapGet("/users", () => "All users")
   .WithName("GetAllUsers");

Required for:

  • URL generation
  • OpenAPI documentation
  • Testing

3. Organize with Route Groups

var users = app.MapGroup("/users").WithTags("Users");
users.MapGet("/", GetAllUsers).WithName("GetAllUsers");
users.MapGet("/{id}", GetUser).WithName("GetUser");
users.MapPost("/", CreateUser).WithName("CreateUser");

4. Extract Handler Methods

Instead of inline:

app.MapGet("/users", () => { /* 50 lines */ });

Use local functions:

app.MapGet("/users", GetAllUsers);

static IResult GetAllUsers(UserService service)
{
    var users = service.GetAll();
    return Results.Ok(users);
}

5. Use Record Types

Perfect for DTOs:

record User(int Id, string Name, string Email);
record CreateUserRequest(string Name, string Email);

ClaudeStack.API uses this pattern:

record WeatherForecast(DateOnly Date, int TemperatureC, string Summary);

6. Explicit Using Statements

This project has ImplicitUsings disabled. Always include:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

7. Validate Input

app.MapPost("/users", (CreateUserRequest request) =>
{
    if (string.IsNullOrEmpty(request.Name))
        return Results.BadRequest("Name is required");

    if (string.IsNullOrEmpty(request.Email))
        return Results.BadRequest("Email is required");

    // Create user
    return Results.Created("/users/1", user);
});

8. Use Filters for Cross-Cutting Concerns

app.MapGet("/admin/users", () => "Admin users")
   .RequireAuthorization("AdminPolicy");

Quick Reference

Endpoint Methods

app.MapGet("/path", handler)       // GET
app.MapPost("/path", handler)      // POST
app.MapPut("/path", handler)       // PUT
app.MapPatch("/path", handler)     // PATCH
app.MapDelete("/path", handler)    // DELETE
app.MapMethods("/path", ["GET", "POST"], handler)  // Custom

Results Helpers

Results.Ok(value)                  // 200 OK
Results.Created("/path", value)    // 201 Created
Results.NoContent()                // 204 No Content
Results.BadRequest(error)          // 400 Bad Request
Results.NotFound()                 // 404 Not Found
Results.Problem(details)           // 500 Internal Server Error

Endpoint Configuration

.WithName("EndpointName")
.WithSummary("Short summary")
.WithDescription("Longer description")
.WithTags("Tag1", "Tag2")
.Produces<Type>(statusCode)
.RequireAuthorization(policy)

Route Groups

var group = app.MapGroup("/prefix");
group.MapGet("/path", handler);

Parameter Binding Sources

(int id)                    // Route parameter
(string? query)             // Query string
(User user)                 // Request body (JSON)
(HttpRequest request)       // HTTP request
(HttpContext context)       // HTTP context
(IService service)          // DI service

  • dotnet-cli-essentials: Running and building API projects
  • aspnet-configuration: Configuring appsettings for APIs
  • mstest-testing-platform: Testing minimal APIs

Additional Resources


Version Information

  • .NET: 10.0 RC 2
  • ASP.NET Core: 10.0.0-rc.2.25502.107
  • OpenAPI Package: Microsoft.AspNetCore.OpenApi 10.0.0-rc.2.25502.107

Minimal APIs are a stable feature as of .NET 6.0+. This project uses .NET 10 RC 2 patterns.