DKNet.AspCore.SlimBus
9.0.41
See the version list below for details.
dotnet add package DKNet.AspCore.SlimBus --version 9.0.41
NuGet\Install-Package DKNet.AspCore.SlimBus -Version 9.0.41
<PackageReference Include="DKNet.AspCore.SlimBus" Version="9.0.41" />
<PackageVersion Include="DKNet.AspCore.SlimBus" Version="9.0.41" />
<PackageReference Include="DKNet.AspCore.SlimBus" />
paket add DKNet.AspCore.SlimBus --version 9.0.41
#r "nuget: DKNet.AspCore.SlimBus, 9.0.41"
#:package DKNet.AspCore.SlimBus@9.0.41
#addin nuget:?package=DKNet.AspCore.SlimBus&version=9.0.41
#tool nuget:?package=DKNet.AspCore.SlimBus&version=9.0.41
DKNet.AspCore.SlimBus
Minimal API integration helpers for SlimMessageBus + FluentResults, enabling terse, consistent, and well-documented REST endpoints over a CQRS-ish message bus abstraction.
This package focuses on the ASP.NET Core surface (endpoint mapping & HTTP translation). Core CQRS contracts and EF Core behaviors live in DKNet.SlimBus.Extensions.
Key Features
- โณ๏ธ One-Liner Endpoint Mapping for commands, queries, paged queries, and void commands
- ๐ฆ Automatic Response Shaping using
FluentResults+ProblemDetails - ๐งพ Standardized Problem Responses via
ProducesCommons()contract - ๐ Pagination Wrapper (
PagedResult<T>) forIPagedList<T>โ stable JSON shape - ๐ Uniform HTTP Semantics (POST = create vs update; null query response โ 404)
- ๐งช Test-Friendly pure extension methods (logic inside bus + results)
Installation
dotnet add package DKNet.AspCore.SlimBus
Also install (if not already):
dotnet add package DKNet.SlimBus.Extensions
When To Use
| Scenario | Use This Extension |
|---|---|
| You have SlimMessageBus handlers and want quick HTTP Minimal API exposure | โ |
You use FluentResults for domain outcomes |
โ |
| You want consistent OpenAPI metadata for common error codes | โ |
| You need multi-endpoint CRUD for a resource without hand-writing boilerplate | โ |
Quick Start
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
// SlimBus + handlers (from DKNet.SlimBus.Extensions)
services.AddSlimBusForEfCore(b =>
{
b.WithProviderMemory()
.AutoDeclareFrom(typeof(CreateProductHandler).Assembly)
.AddJsonSerializer();
});
var app = builder.Build();
var products = app.MapGroup("/products");
products
.MapGet<GetProduct, ProductResult>("/{id}")
.WithName("GetProduct");
products
.MapGetPage<GetProductsPage, ProductResult>("/")
.WithName("GetProductsPage");
products
.MapPost<CreateProduct, ProductResult>("/")
.WithName("CreateProduct");
products
.MapPut<UpdateProduct, ProductResult>("/{id}")
.WithName("UpdateProduct");
products
.MapDelete<DeleteProduct>("/{id}")
.WithName("DeleteProduct");
app.Run();
Endpoint Mapping API
All methods extend RouteGroupBuilder and infer OpenAPI metadata.
| Method | Generic Constraints | Behavior |
|---|---|---|
MapGet<TQuery,TResponse> |
TQuery : Fluents.Queries.IWitResponse<TResponse> |
Sends query, returns 200 + body or 404 if null |
MapGetPage<TQuery,TItem> |
TQuery : Fluents.Queries.IWitPageResponse<TItem> |
Wraps IPagedList<TItem> in PagedResult<TItem> |
MapPost<TCommand,TResponse> |
TCommand : Fluents.Requests.IWitResponse<TResponse> |
Sends command, 201 Created (location "/") on success |
MapPost<TCommand> |
TCommand : Fluents.Requests.INoResponse |
200 OK / Problem |
MapPut<TCommand,TResponse> |
TCommand : Fluents.Requests.IWitResponse<TResponse> |
200 OK with value or Problem |
MapPut<TCommand> |
TCommand : Fluents.Requests.INoResponse |
200 OK / Problem |
MapPatch<TCommand,TResponse> |
same as Put | Partial update semantics |
MapPatch<TCommand> |
same as Put | Partial update no response |
MapDelete<TCommand,TResponse> |
TCommand : Fluents.Requests.IWitResponse<TResponse> |
200 OK with value / Problem |
MapDelete<TCommand> |
TCommand : Fluents.Requests.INoResponse |
200 OK / Problem |
All return a RouteHandlerBuilder enabling further customization (e.g., .RequireAuthorization()).
Common Response Metadata
Call .ProducesCommons() automatically (already applied internally by the mapping helpers) to register standardized error codes:
- 400 (ProblemDetails) validation / domain errors
- 401 / 403 auth/authz
- 404 not found (for null query result)
- 409 conflict
- 429 rate limiting
- 500 server error
FluentResults โ HTTP Translation
ResultResponseExtensions define:
public static IResult Response<T>(this IResult<T> result, bool isCreated = false);
public static IResult Response(this IResultBase result, bool isCreated = false);
Rules:
- Failure โ
ProblemDetails(400 by default) - Success +
isCreatedโ201 Createdwith payload - Success + null value โ
200 Ok(no body) - Success + value โ JSON body
ProblemDetails Extensions
result.ToProblemDetails(); // From IResultBase
modelState.ToProblemDetails(); // From ModelStateDictionary
Aggregates distinct error messages into extensions.errors.
Example output:
{
"status": 400,
"type": "BadRequest",
"title": "Error",
"detail": "Name is required",
"errors": ["Name is required", "Price must be positive"]
}
Pagination Wrapper
PagedResult<T> converts an IPagedList<T> into a transport-friendly DTO:
{
"pageNumber": 1,
"pageSize": 20,
"pageCount": 7,
"totalItemCount": 123,
"items": [ { /* ... */ } ]
}
Returned automatically by MapGetPage.
Defining Requests & Handlers (from DKNet.SlimBus.Extensions)
public record GetProduct : Fluents.Queries.IWitResponse<ProductDto>
{
public Guid Id { get; init; }
}
public class GetProductHandler : Fluents.Queries.IHandler<GetProduct, ProductDto>
{
private readonly AppDbContext _db; private readonly IMapper _m;
public GetProductHandler(AppDbContext db, IMapper m) { _db = db; _m = m; }
public async Task<ProductDto?> Handle(GetProduct q, CancellationToken ct) =>
await _db.Products.Where(p => p.Id == q.Id)
.Select(p => _m.Map<ProductDto>(p))
.FirstOrDefaultAsync(ct);
}
Binding With [AsParameters]
For GET endpoints the query object is bound via [AsParameters] automatically when using the helpers, enabling clean record definitions:
public record GetProductsPage(int PageIndex = 0, int PageSize = 20) : Fluents.Queries.IWitPageResponse<ProductDto>;
Composing Policies / Filters
products
.MapPost<CreateProduct, ProductResult>("/")
.RequireAuthorization("ProductsWrite")
.AddEndpointFilter(new LoggingFilter());
Error Scenarios & Status Codes
| Situation | Result Pattern | HTTP | Body |
|---|---|---|---|
| Domain validation fails | Result.Fail("msg") |
400 | ProblemDetails |
| Query returns null | null |
404 | ProblemDetails (none) |
| Command succeeds (create) | Result.Ok(value) + created flag |
201 | JSON |
| Command succeeds (no value) | Result.Ok() |
200 | (empty) |
| Unhandled exception | n/a | 500 | (standard) |
Extending
Add your own composite methods:
public static class ProductEndpointGroup
{
public static RouteGroupBuilder MapProductEndpoints(this IEndpointRouteBuilder app)
{
var g = app.MapGroup("/products");
g.MapGet<GetProduct, ProductDto>("/{id}");
g.MapPost<CreateProduct, ProductDto>("/");
return g;
}
}
Testing Patterns
Because the endpoint methods only orchestrate bus + translation, prefer unit testing handlers and a minimal integration test asserting mapping correctness:
// Arrange: host with in-memory bus stub
// Act: HTTP call
// Assert: status + payload shape
Versioning & Compatibility
| Package | Purpose |
|---|---|
| DKNet.AspCore.SlimBus | HTTP layer & endpoint helpers |
| DKNet.SlimBus.Extensions | Core CQRS abstractions, EF behaviors |
Targets .NET 9+. Uses ASP.NET Core Minimal APIs.
Roadmap / Ideas
- Optional Location URI delegate for Created responses
- Customizable default problem title / type mapping
- OpenTelemetry activity tagging
- Inline endpoint filter helpers (validation, caching)
Contributing
PRs welcome. Keep helpers minimal and side-effect free. Larger concerns (transactions, persistence, events) belong in the core extensions library.
License
MIT ยฉ DKNet
See Also
DKNet.SlimBus.Extensions(core CQRS + EF integration)- SlimMessageBus
- FluentResults
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 was computed. 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. |
-
net9.0
- DKNet.SlimBus.Extensions (>= 9.0.41)
- FluentResults (>= 4.0.0)
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 |
|---|---|---|
| 9.5.28 | 0 | 10/27/2025 |
| 9.5.27 | 26 | 10/27/2025 |
| 9.5.26 | 29 | 10/27/2025 |
| 9.5.25 | 28 | 10/26/2025 |
| 9.5.24 | 30 | 10/25/2025 |
| 9.5.23 | 31 | 10/25/2025 |
| 9.5.22 | 31 | 10/25/2025 |
| 9.5.21 | 95 | 10/24/2025 |
| 9.5.20 | 108 | 10/23/2025 |
| 9.5.19 | 101 | 10/23/2025 |
| 9.5.18 | 136 | 10/22/2025 |
| 9.5.17 | 136 | 10/17/2025 |
| 9.5.16 | 129 | 10/17/2025 |
| 9.5.15 | 158 | 10/15/2025 |
| 9.5.14 | 156 | 10/14/2025 |
| 9.5.13 | 157 | 10/14/2025 |
| 9.5.12 | 150 | 10/14/2025 |
| 9.5.11 | 149 | 10/14/2025 |
| 9.5.10 | 146 | 10/14/2025 |
| 9.5.9 | 157 | 10/13/2025 |
| 9.5.8 | 69 | 10/11/2025 |
| 9.5.7 | 100 | 10/10/2025 |
| 9.5.6 | 103 | 10/10/2025 |
| 9.5.5 | 111 | 10/10/2025 |
| 9.5.4 | 118 | 10/10/2025 |
| 9.5.3 | 147 | 10/8/2025 |
| 9.5.2 | 150 | 10/8/2025 |
| 9.5.1 | 165 | 10/7/2025 |
| 9.0.42 | 160 | 10/6/2025 |
| 9.0.41 | 163 | 10/2/2025 |
| 9.0.40 | 161 | 10/2/2025 |