Axent.Core
1.2.0
See the version list below for details.
dotnet add package Axent.Core --version 1.2.0
NuGet\Install-Package Axent.Core -Version 1.2.0
<PackageReference Include="Axent.Core" Version="1.2.0" />
<PackageVersion Include="Axent.Core" Version="1.2.0" />
<PackageReference Include="Axent.Core" />
paket add Axent.Core --version 1.2.0
#r "nuget: Axent.Core, 1.2.0"
#:package Axent.Core@1.2.0
#addin nuget:?package=Axent.Core&version=1.2.0
#tool nuget:?package=Axent.Core&version=1.2.0
Axent
Axent is a lightweight, high-performance .NET library for implementing the CQRS pattern with minimal boilerplate. It provides a source-generated, typed request/response pipeline — currently ~2x faster than MediatR (v12.5) with fewer allocations.
Why Axent?
- 🚀 Fast: source generated dispatch with zero reflection
- 🧩 Minimal: very little setup
- 🧠 Strongly typed, extensible pipelines for cross-cutting concerns
- 🌐 First class ASP.NET Core integration
- ⚙️ Built for modern .NET (8+)
📦 Features
- Minimal setup and boilerplate
- Source-generated dispatch — no reflection at runtime
- Typed pipelines with support for generic and request-specific pipes
- Separate marker interfaces for commands and queries (
ICommand<TResponse>,IQuery<TResponse>) - Built-in support for transactions, logging, and error handling via pipeline options
- ASP.NET Core integration
- .NET 8+ optimized
Prerequisites
- .NET 8 or later
🚀 Getting Started
1. Install Packages
dotnet add package Axent.Core --version 1.2.0
dotnet add package Axent.Extensions.AspNetCore --version 1.2.0
2. Register Services
builder.Services.AddAxent()
.AddRequestHandlers(AssemblyProvider.Current);
3. Create a Request and Handler
- IQuery<TResponse> for read operations
- ICommand<TResponse> for write operations
- IRequest<TResponse> if you don't want to differentiate
- IRequestHandler<TRequest, TResponse> to handle them
using Axent.Abstractions;
namespace Axent.ExampleApi;
internal sealed class ExampleQuery : IQuery
{
public required string Message { get; init; }
}
internal sealed class ExampleQueryHandler : IRequestHandler
{
private readonly ILogger _logger;
public ExampleQueryHandler(ILogger logger)
{
_logger = logger;
}
public ValueTask<Response> HandleAsync(RequestContext context, CancellationToken cancellationToken = default)
{
_logger.LogInformation("Message from request '{Message}'", context.Request.Message);
return ValueTask.FromResult(Response.Success(Unit.Value));
}
}
4. Send a Request
Inject ISender into endpoints or application services.
app.MapGet("/api/example", async (ISender sender, CancellationToken cancellationToken) =>
{
var response = await sender.SendAsync(new ExampleQuery { Message = "Hello World!" }, cancellationToken);
return response.ToResult();
});
🔁 Pipelines
Pipelines allow you to add cross-cutting behavior such as:
- Logging
- Validation
- Metrics
- Authorization
- Caching
Implement
IAxentPipe<TRequest, TResponse>
Pipes are executed in registration order before the handler.
🌐 Generic Pipe
Runs for all request types.
internal sealed class LoggingPipe : IAxentPipe
{
private readonly ILogger<LoggingPipe> _logger;
public LoggingPipe(ILogger<LoggingPipe> logger)
{
_logger = logger;
}
public ValueTask<Response> ProcessAsync(IPipelineChain chain, RequestContext context, CancellationToken cancellationToken = default)
{
_logger.LogInformation("Handling {Request}", typeof(TRequest).Name);
return chain.NextAsync(context, cancellationToken);
}
}
Registration
builder.Services.AddAxent()
.AddRequestHandlers(AssemblyProvider.Current)
.AddPipe(typeof(LoggingPipe));
🎯 Request Specific Pipe
Runs only for a single request type.
internal sealed class OtherRequestPipe : IAxentPipe
{
private readonly ILogger _logger;
public OtherRequestPipe(ILogger logger)
{
_logger = logger;
}
public ValueTask<Response> ProcessAsync(IPipelineChain chain, RequestContext context, CancellationToken cancellationToken = default)
{
_logger.LogInformation("Running pipe for OtherRequest");
return chain.NextAsync(context, cancellationToken);
}
}
Registration
builder.Services.AddAxent()
.AddRequestHandlers(AssemblyProvider.Current)
.AddPipe();
⚙️ Configuration
Customize behavior via AxentOptions.
builder.Services.AddAxent(options =>
{
options.ErrorHandling = new AxentErrorHandlingOptions
{
EnableDetailedExceptionResponse = false
};
options.Logging = new AxentLoggingOptions
{
EnableRequestLogging = true
};
options.Transactions = new AxentTransactionOptions
{
UseTransactions = true
};
});
| Option | Description | Default |
|---|---|---|
ErrorHandling |
Enables pipeline exception handling. EnableDetailedExceptionResponse includes exception details in responses. If null, exceptions propagate. | null |
Logging.EnableRequestLogging |
Logs the full request object via ILogger before processing. Avoid in production if requests contain sensitive data. |
false |
Transactions.UseTransactions |
Wraps ICommand handlers in a TransactionScope. Has no effect on IQuery handlers. |
true |
Transactions.TransactionOptions |
Isolation level and timeout settings. | ReadCommitted, 180s |
Transactions.TransactionScopeOption |
Interaction with ambient transactions. | Required |
Transactions.TransactionScopeAsyncFlowOption |
Controls async transaction flow. | Enabled |
📊 Benchmarks
Axent (Source Generated Dispatch)
BenchmarkDotNet v0.14.0, Windows 11 (10.0.26200.7840)
Unknown processor
.NET SDK 10.0.200-preview.0.26103.119
[Host] : .NET 8.0.23 (8.0.2325.60607), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI [AttachedDebugger]
DefaultJob : .NET 8.0.23 (8.0.2325.60607), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'SendAsync (cold)' | 36.74 ns | 0.741 ns | 1.702 ns | 1.00 | 0.06 | 0.0196 | 328 B | 1.00 |
| 'SendAsync (warm, same instance)' | 33.97 ns | 0.423 ns | 0.353 ns | 0.93 | 0.04 | 0.0181 | 304 B | 0.93 |
MediatR (v12.5.0)
BenchmarkDotNet v0.14.0, Windows 11 (10.0.26200.7840)
Unknown processor
.NET SDK 10.0.200-preview.0.26103.119
[Host] : .NET 8.0.23 (8.0.2325.60607), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI [AttachedDebugger]
DefaultJob : .NET 8.0.23 (8.0.2325.60607), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
| Method | Mean | Error | StdDev | Gen0 | Allocated |
|---|---|---|---|---|---|
| 'Send (cold)' | 79.03 ns | 1.526 ns | 2.713 ns | 0.0257 | 432 B |
| 'Send (warm, same instance)' | 79.21 ns | 1.566 ns | 3.783 ns | 0.0243 | 408 B |
🤝 Contributing
Contributions are welcome. If you find a bug, have an improvement, or want to propose a feature:
- Open an issue
- Start a discussion
- Submit a pull request
📄 License
This project is licensed under the Apache License 2.0. See LICENSE for details.
| Product | Versions 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 was computed. 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. |
-
net8.0
- Axent.Abstractions (>= 1.2.0)
- Microsoft.AspNetCore.Http.Abstractions (>= 2.3.9)
- Microsoft.Extensions.DependencyInjection (>= 8.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.3)
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 |
|---|---|---|
| 1.2.2 | 102 | 3/9/2026 |
| 1.2.1 | 126 | 3/9/2026 |
| 1.2.1-alpha.2 | 53 | 3/8/2026 |
| 1.2.1-alpha.1 | 50 | 3/8/2026 |
| 1.2.0 | 113 | 3/8/2026 |
| 1.1.0 | 110 | 2/28/2026 |
| 1.1.0-alpha.3 | 45 | 2/28/2026 |
| 1.1.0-alpha.2 | 50 | 2/28/2026 |
| 1.0.1 | 103 | 2/26/2026 |
| 1.0.0 | 102 | 2/25/2026 |
| 0.0.1 | 102 | 2/25/2026 |