Axent.Extensions.AspNetCore 1.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Axent.Extensions.AspNetCore --version 1.1.0
                    
NuGet\Install-Package Axent.Extensions.AspNetCore -Version 1.1.0
                    
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="Axent.Extensions.AspNetCore" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Axent.Extensions.AspNetCore" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Axent.Extensions.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 Axent.Extensions.AspNetCore --version 1.1.0
                    
#r "nuget: Axent.Extensions.AspNetCore, 1.1.0"
                    
#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 Axent.Extensions.AspNetCore@1.1.0
                    
#: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=Axent.Extensions.AspNetCore&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Axent.Extensions.AspNetCore&version=1.1.0
                    
Install as a Cake Tool

Axent

Axent Logo

NuGet NuGet NuGet Downloads License

Axent is a lightweight, high-performance .NET library for implementing CQRS patterns with minimal boilerplate. It provides a simple request/response pipeline and allows adding custom processors for advanced scenarios.


Features

  • Minimal setup for CQRS in .NET applications
  • Request/response handling with RequestHandler<TRequest, TResponse>
  • Extensible pipelines using IAxentPipe<TRequest, TResponse>
  • Optimized for performance and simplicity
  • Works seamlessly with ASP.NET Core
  • Choose between a source generated or reflection based sender implementation

Prerequisites

  • .NET 8 or later

Getting started

1. Install Packages

dotnet add package Axent.Core --version 1.1.0
dotnet add package Axent.Extensions.AspNetCore --version 1.1.0

2. Register Services

builder.Services.AddHttpContextAccessor()
builder.Services.AddAxent()
    .AddRequestHandlers(AssemblyProvider.Current);

3. Implement a Request Handler

Example showing a request that logs a message

using Axent.Abstractions;
using Axent.Core;

namespace Axent.ExampleApi;

internal sealed class ExampleRequest : IRequest<Unit>
{
    public required string Message { get; init; }
}

internal sealed class ExampleRequestHandler : RequestHandler<ExampleRequest, Unit>
{
    private readonly ILogger<ExampleRequestHandler> _logger;

    public ExampleRequestHandler(ILogger<ExampleRequestHandler> logger)
    {
        _logger = logger;
    }

    public override Task<Response<Unit>> HandleAsync(RequestContext<ExampleRequest> context, CancellationToken cancellationToken = default)
    {
        _logger.LogInformation("Message from request '{0}'", context.Request.Message);
        return Task.FromResult(Response.Success(Unit.Value));
    }
}

4. Call the Request Handler in an API Endpoint

app.MapGet("/api/example", async (ISender sender, CancellationToken cancellationToken) =>
{
    var request = new ExampleRequest
    {
        Message = "Hello World!"
    };

    var response = await sender.SendAsync(request, cancellationToken);
    return response.ToResult();
});

Pipelines

Axent allows you to add custom processors to your request pipeline by implementing IAxentPipe<TRequest, TResponse>. This is useful for logging, validation, metrics, or any cross-cutting concerns.

Generic Pipe

internal sealed class ExampleRequestPipe<TRequest, TResponse> : IAxentPipe<TRequest, TResponse>
{
    private readonly ILogger<ExampleRequestPipe<TRequest, TResponse>> _logger;

    public ExampleRequestPipe(ILogger<ExampleRequestPipe<TRequest, TResponse>> logger)
    {
        _logger = logger;
    }

    public ValueTask<Response<TResponse>> ProcessAsync(Func<ValueTask<Response<TResponse>>> next, RequestContext<TRequest> context, CancellationToken cancellationToken = default)
    {
        _logger.LogInformation("This pipe runs during every request.");
        return next();
    }
}

builder.Services.AddAxent()
    .AddRequestHandlers(AssemblyProvider.Current)
    .AddPipe(typeof(ExampleRequestPipe<,>));

This pipe executes for every request handled by Axent.

Specific Pipe

internal sealed class OtherRequestPipe : IAxentPipe<OtherRequest, Unit>
{
    private readonly ILogger<OtherRequestPipe> _logger;

    public OtherRequestPipe(ILogger<OtherRequestPipe> logger)
    {
        _logger = logger;
    }


    public ValueTask<Response<Unit>> ProcessAsync(Func<ValueTask<Response<Unit>>> next, RequestContext<OtherRequest> context, CancellationToken cancellationToken = default)
    {
        _logger.LogInformation("I only run during other request");
        return next();
    }
}

builder.Services.AddAxent()
    .AddRequestHandlers(AssemblyProvider.Current)
    .AddPipe<OtherRequestPipe>();

This pipe executes for every request of the type OtherRequest

Options

AxentOptions

AxentOptions allows you to configure optional settings that modify the behavior of the Axent library.

public sealed class AxentOptions
{
    /// <summary>
    /// Determines whether to use the source-generated sender implementation.
    /// Defaults to true.
    /// </summary>
    public bool UseSourceGeneratedSender { get; set; } = true;
}

Using Reflection Based Sender Implementation

You can switch to the reflection-based sender by setting UseSourceGeneratedSender to false:

builder.Services.AddAxent(o => o.UseSourceGeneratedSender = false)
    .AddRequestHandlers(AssemblyProvider.Current)
    .AddPipe<OtherRequestPipe>();

By default, if no options are provided, the source-generated sender is used.

Benchmark

Source Generated Dispatch

BenchmarkDotNet v0.14.0, Windows 11 (10.0.26200.7840)
11th Gen Intel Core i9-11900K 3.50GHz, 1 CPU, 16 logical and 8 physical cores
.NET SDK 9.0.203
  [Host]     : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
  DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Method Mean Error StdDev Median Ratio RatioSD Gen0 Allocated Alloc Ratio
'SendAsync (cold)' 267.4 ns 20.59 ns 60.72 ns 229.1 ns 1.05 0.32 0.0753 632 B 1.00
'SendAsync (warm, same instance)' 220.6 ns 4.37 ns 6.12 ns 219.7 ns 0.86 0.17 0.0725 608 B 0.96

Reflection Dispatch

BenchmarkDotNet v0.14.0, Windows 11 (10.0.26200.7840)
11th Gen Intel Core i9-11900K 3.50GHz, 1 CPU, 16 logical and 8 physical cores
.NET SDK 9.0.203
  [Host]     : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
  DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Method Mean Error StdDev Median Ratio RatioSD Gen0 Allocated Alloc Ratio
'SendAsync (cold)' 1,149.5 ns 56.12 ns 165.46 ns 1,205.2 ns 1.02 0.22 0.1249 1.02 KB 1.00
'SendAsync (warm, same instance)' 853.3 ns 16.94 ns 25.35 ns 852.8 ns 0.76 0.13 0.1221 1 KB 0.98

Contributing

Contributions are welcome! Please open an issue or pull request for bug fixes, improvements, or new features.

License

This project is licensed under the Apache 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 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. 
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
1.2.2 104 3/9/2026
1.2.1 97 3/9/2026
1.2.1-alpha.2 51 3/8/2026
1.2.1-alpha.1 46 3/8/2026
1.2.0 96 3/8/2026
1.1.0 94 2/28/2026
1.1.0-alpha.3 45 2/28/2026
1.1.0-alpha.2 49 2/28/2026
1.0.1 88 2/26/2026
1.0.0 87 2/25/2026
0.0.1 87 2/25/2026