Postie.AspNetCore 1.0.1

dotnet add package Postie.AspNetCore --version 1.0.1
                    
NuGet\Install-Package Postie.AspNetCore -Version 1.0.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="Postie.AspNetCore" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Postie.AspNetCore" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Postie.AspNetCore" />
                    
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 Postie.AspNetCore --version 1.0.1
                    
#r "nuget: Postie.AspNetCore, 1.0.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 Postie.AspNetCore@1.0.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=Postie.AspNetCore&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Postie.AspNetCore&version=1.0.1
                    
Install as a Cake Tool

Postie.AspNetCore

Map CQRS commands and queries directly to ASP.NET Core minimal API endpoints — MapQuery, MapCommand, MapPostCreate and friends — with the right status codes, Location headers, OpenAPI metadata and full control over request binding. Mediator-agnostic: the engine dispatches through a single abstraction, so you bring your own mediator. Part of Postiefree forever, MIT licensed.

dotnet add package Postie.AspNetCore

This package is the endpoint engine. Pair it with an adapter that registers an IEndpointDispatcher:

Mapping

using Postie.AspNetCore;

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

orders.MapQuery<GetOrders, IReadOnlyList<Order>>("/");
orders.MapQuery<GetOrder, Order>("/{id}").WithName("GetOrder");
orders.MapPostCreate<CreateOrder, Order>("/", "GetOrder", o => new { id = o.Id });
orders.MapPutCommand<UpdateOrder, Order>("/{id}", binding: RequestBinding.Parameters);
orders.MapDeleteCommand<DeleteOrder>("/{id}");

Every method returns the RouteHandlerBuilder, so you can chain .WithName(...), .RequireAuthorization(...) and so on.

Method Verb Success
MapQuery<TQuery, TResponse> GET (default) / POST / QUERY 200 / 404 on null
MapCommand<TCommand, TResponse> / MapCommand<TCommand> POST 200 / 204
MapPutCommand<TCommand, TResponse> / MapPutCommand<TCommand> PUT 200 / 204
MapPatchCommand<TCommand, TResponse> PATCH 200
MapPostCreate<TCommand, TResponse> / MapPutCreate<...> POST / PUT 201 + Location
MapDeleteCommand<TCommand> / MapDeleteCommand<TCommand, TResponse> DELETE 204 / 200
MapStreamQuery<TQuery, TResponse> GET (default) / POST / QUERY 200 (streamed)

Pass a status code to override the default (e.g. MapCommand<Submit, Receipt>("/submit", StatusCodes.Status202Accepted)).

MapStreamQuery maps a streaming query (returning IAsyncEnumerable<TResponse>) and requires an IStreamEndpointDispatcher — a separate, optional companion to IEndpointDispatcher that the Postie and MediatR adapters register automatically. A roll-your-own mediator only needs to implement it to map streams.

MapStreamQuery responses are written as a JSON array serialised incrementally — the first items reach the client while later ones are still being produced, and memory stays flat however long the stream runs. Because the 200 status line is sent before enumeration finishes, a handler failure mid-stream aborts the connection with truncated JSON rather than producing an error status.

Queries with a request body

Criteria too rich for a query string — nested filters, sort sets, paging — can bind from the body by picking the HTTP method for the query. POST and the HTTP QUERY method bind the query from the request body by default; an explicit RequestBinding overrides any default:

public record SearchOrders(OrderFilter Filter, Paging Page, Sort[] Sort) : IQuery<PagedResult<Order>>;

app.MapQuery<SearchOrders, PagedResult<Order>>("/orders/search", QueryMethod.Post);
app.MapQuery<SearchOrders, PagedResult<Order>>("/orders/search", QueryMethod.Query);

The response contract does not change with the method: a null result is 404, anything else is 200. The HTTP QUERY method is safe and idempotent like GET while carrying a body like POST — the semantically ideal fit for a query — but ecosystem support is still maturing: a spike against Microsoft.AspNetCore.OpenApi (10.0.10, on .NET 10) found that a QUERY-mapped endpoint is silently omitted from the generated /openapi/v1.json — document generation succeeds and the GET and POST endpoints appear correctly, but the QUERY endpoint has no entry at all — and intermediaries or clients may not recognise the method yet. POST works everywhere today.

Not found

Queries returning a reference type respond 404 Not Found when the dispatched result is null, and advertise the 404 in OpenAPI metadata. Value-type queries can't be null and don't advertise it. Collection queries should return empty collections, not null.

Request binding

Queries bind idiomatically for their QueryMethod — route, query and header values for GET, the request body for POST and QUERY — unless an explicit RequestBinding overrides that. Command methods take a RequestBinding that defaults to Body for POST/PUT/PATCH and Parameters for DELETE:

// Default: whole command from the JSON body.
orders.MapCommand<CreateOrder, Order>("/");

// Hybrid: id from the route, payload from the body.
public record UpdateOrder([FromRoute] int Id, [FromBody] OrderDetails Details) : ICommand<Order>;
orders.MapPutCommand<UpdateOrder, Order>("/{id}", binding: RequestBinding.Parameters);

Mapping a Body-bound command whose members carry [FromRoute]/[FromQuery]/[FromHeader]/[FromForm] fails at startup with a message naming the offending members — those attributes only take effect with Parameters binding.

Errors

This package does not translate exceptions — handlers throw, and your exception handling maps them to responses. Postie's mappings only advertise the responses they produce themselves; chain .Produces(...)/.ProducesValidationProblem() for responses your pipeline adds. For FluentValidation, Postie.AspNetCore.FluentValidation maps ValidationException to an RFC 9457 400 problem-details response; or register your own IExceptionHandler.

License

MIT. See LICENSE.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Postie.AspNetCore:

Package Downloads
Postie.Cqrs.AspNetCore

Postie.Cqrs adapter for Postie.AspNetCore — dispatches minimal API endpoints through Postie's own mediator.

Postie.AspNetCore.MediatR

MediatR adapter for Postie.AspNetCore — dispatch minimal API endpoints through MediatR, keeping your existing IRequest types.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 1,218 7/22/2026
1.0.0 244 7/22/2026