NetEvolve.Pulse.AspNetCore 0.17.3

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

NetEvolve.Pulse.AspNetCore

NuGet Version NuGet Downloads License

NetEvolve.Pulse.AspNetCore provides IEndpointRouteBuilder extension methods that map Pulse mediator commands and queries directly to ASP.NET Core Minimal API HTTP endpoints. Eliminate the boilerplate of endpoint lambdas that only forward to IMediator.

Features

  • MapCommand<TCommand, TResponse>: Maps a command to an HTTP endpoint returning 200 OK with the response. Defaults to POST when no method is specified; accepts any CommandHttpMethod value.
  • MapCommand<TCommand>: Maps a void command to an HTTP endpoint returning 204 No Content. Defaults to POST when no method is specified; accepts any CommandHttpMethod value.
  • MapQuery<TQuery, TResponse>: Maps a query to a GET endpoint returning 200 OK with the result.
  • CommandHttpMethod enum: Strongly-typed HTTP method selection — Post, Put, Patch, Delete. GET is excluded by design since commands are state-changing operations.
  • CancellationToken propagation: Automatically propagates the HTTP request cancellation token.
  • OpenAPI compatible: Returns typed results (TypedResults) so WithOpenApi() produces correct response schemas.
  • DI-based: IMediator is resolved from the request scope at runtime — no compile-time dependency on NetEvolve.Pulse.

Installation

NuGet Package Manager

Install-Package NetEvolve.Pulse.AspNetCore

.NET CLI

dotnet add package NetEvolve.Pulse.AspNetCore

PackageReference

<PackageReference Include="NetEvolve.Pulse.AspNetCore" Version="x.x.x" />

Quick Start

using NetEvolve.Pulse;

var builder = WebApplication.CreateBuilder(args);

// Register Pulse and handlers
builder.Services.AddPulse();
builder.Services.AddScoped<ICommandHandler<CreateOrderCommand, OrderResult>, CreateOrderHandler>();
builder.Services.AddScoped<ICommandHandler<UpdateOrderCommand, OrderResult>, UpdateOrderHandler>();
builder.Services.AddScoped<ICommandHandler<DeleteOrderCommand, Void>, DeleteOrderHandler>();
builder.Services.AddScoped<IQueryHandler<GetOrderQuery, OrderDto>, GetOrderHandler>();

var app = builder.Build();

// Map commands and queries — no boilerplate lambdas needed
app.MapCommand<CreateOrderCommand, OrderResult>("/orders");                                    // POST  /orders
app.MapCommand<UpdateOrderCommand, OrderResult>("/orders/{id}", CommandHttpMethod.Put);        // PUT   /orders/{id}
app.MapCommand<DeleteOrderCommand>("/orders/{id}", CommandHttpMethod.Delete);                  // DELETE /orders/{id}
app.MapQuery<GetOrderQuery, OrderDto>("/orders/{id}");                                         // GET   /orders/{id}

app.Run();

Without this package you would write:

app.MapPost("/orders", async (CreateOrderCommand cmd, IMediator mediator, CancellationToken ct) =>
    Results.Ok(await mediator.SendAsync<CreateOrderCommand, OrderResult>(cmd, ct)));

app.MapPut("/orders/{id}", async (UpdateOrderCommand cmd, IMediator mediator, CancellationToken ct) =>
    Results.Ok(await mediator.SendAsync<UpdateOrderCommand, OrderResult>(cmd, ct)));

app.MapDelete("/orders/{id}", async ([FromBody] DeleteOrderCommand cmd, IMediator mediator, CancellationToken ct) =>
{
    await mediator.SendAsync<DeleteOrderCommand>(cmd, ct);
    return Results.NoContent();
});

app.MapGet("/orders/{id}", async ([AsParameters] GetOrderQuery query, IMediator mediator, CancellationToken ct) =>
    Results.Ok(await mediator.QueryAsync<GetOrderQuery, OrderDto>(query, ct)));

Usage

Commands with a Response

MapCommand<TCommand, TResponse> binds the request body to TCommand, sends it via IMediator.SendAsync, and returns 200 OK with the result. The default HTTP method is POST; use the CommandHttpMethod parameter to choose a different method:

// POST /orders  (default)
app.MapCommand<CreateOrderCommand, OrderResult>("/orders");

// PUT /orders/{id}
app.MapCommand<UpdateOrderCommand, OrderResult>("/orders/{id}", CommandHttpMethod.Put);

// PATCH /orders/{id}
app.MapCommand<PatchOrderCommand, OrderResult>("/orders/{id}", CommandHttpMethod.Patch);
public record CreateOrderCommand(string Sku, int Quantity) : ICommand<OrderResult>;
public record UpdateOrderCommand(Guid Id, string Sku, int Quantity) : ICommand<OrderResult>;
public record OrderResult(Guid OrderId, string Status);

Void Commands

MapCommand<TCommand> binds the request body to TCommand, sends it via IMediator.SendAsync, and returns 204 No Content. The default HTTP method is POST:

// POST /orders/cancel  (default)
app.MapCommand<CancelOrderCommand>("/orders/cancel");

// DELETE /orders/{id}
app.MapCommand<DeleteOrderCommand>("/orders/{id}", CommandHttpMethod.Delete);
public record CancelOrderCommand(Guid Id) : ICommand;
public record DeleteOrderCommand(Guid Id) : ICommand;

Queries

MapQuery<TQuery, TResponse> registers a GET endpoint that binds route parameters and query string to TQuery using [AsParameters], executes the query via IMediator.QueryAsync, and returns 200 OK with the result:

app.MapQuery<GetOrderQuery, OrderDto>("/orders/{id}");
public record GetOrderQuery(Guid Id) : IQuery<OrderDto>;
public record OrderDto(Guid Id, string Sku, string Status);

CommandHttpMethod Enum

The CommandHttpMethod enum controls the HTTP method registered for command endpoints. GET is intentionally excluded because commands are state-changing operations — use MapQuery for read-only operations instead:

Value HTTP Method Typical use
Post (default) POST Create a new resource
Put PUT Replace an existing resource
Patch PATCH Partially update a resource
Delete DELETE Remove a resource

Passing an undefined enum value throws ArgumentOutOfRangeException.

Chaining Endpoint Configuration

All methods return RouteHandlerBuilder, so you can chain Minimal API metadata:

app.MapCommand<CreateOrderCommand, OrderResult>("/orders")
   .WithName("CreateOrder")
   .WithTags("Orders")
   .WithOpenApi()
   .RequireAuthorization();

app.MapCommand<DeleteOrderCommand>("/orders/{id}", CommandHttpMethod.Delete)
   .WithName("DeleteOrder")
   .WithTags("Orders")
   .WithOpenApi()
   .RequireAuthorization();

app.MapQuery<GetOrderQuery, OrderDto>("/orders/{id}")
   .WithName("GetOrder")
   .WithTags("Orders")
   .WithOpenApi()
   .RequireAuthorization("ReadOrders");

Grouping Endpoints

Combine with MapGroup for shared prefixes and metadata:

var orders = app.MapGroup("/orders")
    .WithTags("Orders")
    .RequireAuthorization();

orders.MapCommand<CreateOrderCommand, OrderResult>("/");
orders.MapCommand<UpdateOrderCommand, OrderResult>("/{id}", CommandHttpMethod.Put);
orders.MapCommand<DeleteOrderCommand>("/{id}", CommandHttpMethod.Delete);
orders.MapQuery<GetOrderQuery, OrderDto>("/{id}");

Requirements

  • .NET 8.0, .NET 9.0, or .NET 10.0
  • ASP.NET Core (included in the SDK)
  • NetEvolve.Pulse (or any IMediator implementation) registered in the DI container

Contributing

Contributions are welcome! Please read the Contributing Guidelines before submitting a pull request.

Support

License

This project is licensed under the MIT License - see the LICENSE file for details.


Made with ❤️ by the NetEvolve Team

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.

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
0.17.3 200 3/28/2026