GeneratedEndpoints 9.0.0-preview.1

This is a prerelease version of GeneratedEndpoints.
There is a newer version of this package available.
See the version list below for details.
dotnet add package GeneratedEndpoints --version 9.0.0-preview.1
                    
NuGet\Install-Package GeneratedEndpoints -Version 9.0.0-preview.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="GeneratedEndpoints" Version="9.0.0-preview.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GeneratedEndpoints" Version="9.0.0-preview.1" />
                    
Directory.Packages.props
<PackageReference Include="GeneratedEndpoints" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add GeneratedEndpoints --version 9.0.0-preview.1
                    
#r "nuget: GeneratedEndpoints, 9.0.0-preview.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package GeneratedEndpoints@9.0.0-preview.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=GeneratedEndpoints&version=9.0.0-preview.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=GeneratedEndpoints&version=9.0.0-preview.1&prerelease
                    
Install as a Cake Tool

Banner

GeneratedEndpoints - Attribute-driven, source-generated minimal API endpoints for feature-based development

GeneratedEndpoints is a .NET source generator that automatically wires up Minimal API endpoints from attribute-annotated methods. This simplifies integration of HTTP handlers within Clean Architecture (CA) or Vertical Slice Architecture (VSA) by keeping endpoint definitions inside their features while generating the boilerplate mapping code.

develop nuget downloads

Getting Started

Installation

Add the package to the Minimal API project that will host your endpoints. You can install it with the .NET CLI:

dotnet add package GeneratedEndpoints

Once the package is referenced, the source generator will contribute its attributes and extension methods to the consuming project at build time.

1. Define a request handler

Create a feature class that encapsulates the logic for a single endpoint and decorate its handler method with one of the generated HTTP verb attributes. The attributes live in the Microsoft.AspNetCore.Generated.Attributes namespace and map directly to Minimal API routing methods.

Handler classes can be expressed in whichever style best fits the feature:

  • Instance classes (non-static) allow constructor injection and can expose either instance or static handler methods. When an annotated method is not static the generator will call it on a resolved instance from dependency injection.
  • Static classes make it easy to group stateless functionality. Every annotated method inside must also be static, mirroring standard C# rules.
Instance handler example
using Microsoft.AspNetCore.Generated.Attributes;
using Microsoft.AspNetCore.Http.HttpResults;

namespace Todos.Features;

public sealed class GetTodo
{
    private readonly TodoDbContext _db;

    public GetTodo(TodoDbContext db) => _db = db;

    [MapGet("/todos/{id}", Summary = "Retrieve a todo", Description = "Returns the todo matching the provided identifier.")]
    [Tags("Todos")]
    [RequireAuthorization("Todos.Read")]
    public async Task<Results<Ok<Todo>, NotFound>> HandleAsync(Guid id, CancellationToken cancellationToken)
    {
        var entity = await _db.Todos.FindAsync(new object?[] { id }, cancellationToken);
        return entity is null ? TypedResults.NotFound() : TypedResults.Ok(entity);
    }
}

Key points:

  • Use [MapGet], [MapPost], [MapPut], [MapDelete], [MapPatch], [MapHead], [MapOptions], [MapTrace], or [MapConnect] to describe the HTTP verb and route pattern.
  • Optional Name, Summary, and Description named parameters populate the generated .WithName, .WithSummary, and .WithDescription metadata calls. When omitted, the generator derives the endpoint name from the method name (stripping a trailing Async).
  • Apply standard ASP.NET Core parameter binding attributes ([FromRoute], [FromQuery], [FromBody], [FromServices], [AsParameters], etc.). The generator mirrors them onto the produced delegate so binding behaves exactly as declared.
  • Annotate the class, an individual method, or both with [Tags], [RequireAuthorization], or [DisableAntiforgery]. Class-level metadata is merged onto every generated endpoint, while method-level attributes can refine or augment the settings for a specific handler.
  • Non-static handler classes are automatically registered with dependency injection (as transient services). Their instance methods receive a scoped instance resolved from DI, while static methods continue to behave like any other static helper.
Static handler example

The same attribute-driven approach works for static handler types when no dependencies are needed:

using Microsoft.AspNetCore.Generated.Attributes;
using Microsoft.AspNetCore.Http.HttpResults;

namespace Todos.Features;

public static class ListTodos
{
    [MapGet("/todos")]
    [Tags("Todos")]
    public static Ok<IReadOnlyList<Todo>> Handle()
        => TypedResults.Ok(TodoStore.All);
}

2. Wire up the application

The generator emits extension methods in the Microsoft.AspNetCore.Generated.Routing namespace. Call them during startup to register handler types and map the generated endpoints.

using Microsoft.AspNetCore.Generated.Routing;

var builder = WebApplication.CreateBuilder(args);

// Registers non-static handler classes with the DI container.
builder.Services.AddEndpointHandlers();

var app = builder.Build();

// Maps every method decorated with a Map* attribute.
app.MapEndpointHandlers();

app.Run();

AddEndpointHandlers ensures any non-static handler types can be resolved from dependency injection, while MapEndpointHandlers generates Minimal API route mappings for every annotated method in the application.

3. Compose additional endpoints

Add as many handler classes as needed—each annotated method becomes an endpoint. You can mix synchronous and asynchronous methods, return IResult or typed Results<>, and combine static and instance handlers in the same project. Metadata from attributes composes naturally: class-level attributes are applied to every endpoint, while method-level attributes add to (or override, when relevant) the defaults.

using Microsoft.AspNetCore.Generated.Attributes;
using Microsoft.AspNetCore.Http.HttpResults;

namespace Todos.Features;

[Tags("Todos")]
[RequireAuthorization("Todos.Read")]
public sealed class TodoEndpoints
{
    private readonly TodoDbContext _db;

    public TodoEndpoints(TodoDbContext db) => _db = db;

    [MapGet("/todos/{id}", Summary = "Retrieve a todo")]
    public async Task<Results<Ok<Todo>, NotFound>> GetAsync(Guid id, CancellationToken cancellationToken)
    {
        var entity = await _db.Todos.FindAsync(new object?[] { id }, cancellationToken);
        return entity is null ? TypedResults.NotFound() : TypedResults.Ok(entity);
    }

    [MapDelete("/todos/{id}")]
    [RequireAuthorization("Todos.Write")]
    public static async Task<Results<NoContent, NotFound>> DeleteAsync(
        Guid id,
        [FromServices] TodoDbContext db,
        CancellationToken cancellationToken)
    {
        var entity = await db.Todos.FindAsync(new object?[] { id }, cancellationToken);
        if (entity is null)
            return TypedResults.NotFound();

        db.Todos.Remove(entity);
        await db.SaveChangesAsync(cancellationToken);
        return TypedResults.NoContent();
    }
}

In this example:

  • The class-level [Tags] and [RequireAuthorization] attributes apply to both endpoints, while the method-level [RequireAuthorization] adds an additional policy for the delete handler.
  • GetAsync is an instance method that uses the injected TodoDbContext field, illustrating how non-static handlers can maintain state.
  • DeleteAsync is a static method in the same class and explicitly receives its dependencies via [FromServices], demonstrating that you can mix static and instance methods in a single handler type.

Every new handler will automatically appear in the generated routing table the next time the project builds—no manual MapGet, MapPost, or registration code is required.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.3 779 12/22/2025
10.0.2 1,150 11/17/2025
10.0.1 325 11/17/2025
10.0.0 242 11/16/2025
9.0.0-preview.1 307 9/19/2025