Table of Contents

ASP.NET Core Integration

The Nexum.Extensions.AspNetCore package provides tooling to dispatch Nexum commands and queries from ASP.NET Core minimal APIs and MVC controllers, including Problem Details integration for error responses.

Minimal API dispatch

Minimal APIs and Nexum fit together without any helpers — model-bind straight into the command:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddNexum();

var app = builder.Build();

app.MapPost("/orders", async (
    CreateOrderCommand command,
    ICommandDispatcher dispatcher,
    CancellationToken ct) =>
{
    var id = await dispatcher.DispatchAsync(command, ct);
    return Results.Created($"/orders/{id}", new { Id = id });
});

app.MapGet("/orders/{id:guid}", async (
    Guid id,
    IQueryDispatcher dispatcher,
    CancellationToken ct) =>
{
    var order = await dispatcher.DispatchAsync(new GetOrderQuery(id), ct);
    return order is not null ? Results.Ok(order) : Results.NotFound();
});

app.Run();

Stream endpoints

IStreamQuery<T> pairs naturally with TypedResults.Stream or server-sent events:

app.MapGet("/orders/{id:guid}/events", (
    Guid id,
    IQueryDispatcher dispatcher,
    CancellationToken ct) =>
{
    var stream = dispatcher.StreamAsync(new TailOrderEventsQuery(id), ct);
    return TypedResults.Stream(stream);
});

Problem Details

The package adds a Problem Details middleware that translates common Nexum exceptions into RFC 7807 responses:

app.UseNexumProblemDetails();

Built-in mappings:

Exception HTTP status type
NexumValidationException 400 https://tools.ietf.org/html/rfc9110#section-15.5.1
HandlerNotFoundException 501 urn:nexum:handler-not-found
DispatchDepthExceededException 500 urn:nexum:dispatch-depth-exceeded

You can add custom mappings by registering IProblemDetailsMapper implementations in DI.

Endpoint conventions

For projects that want a light-weight endpoint-per-command pattern, the package provides MapCommand and MapQuery helpers:

app.MapCommand<CreateOrderCommand, Guid>("/orders", HttpVerb.Post);
app.MapQuery<GetOrderQuery, OrderDto?>("/orders/{OrderId:guid}");

These helpers bind the route, model-bind the command, dispatch, and return Results.Ok or Results.NotFound as appropriate.