ConduitR 1.0.2
There is a newer prerelease version of this package available.
See the version list below for details.
See the version list below for details.
dotnet add package ConduitR --version 1.0.2
NuGet\Install-Package ConduitR -Version 1.0.2
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="ConduitR" Version="1.0.2" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ConduitR" Version="1.0.2" />
<PackageReference Include="ConduitR" />
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 ConduitR --version 1.0.2
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: ConduitR, 1.0.2"
#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 ConduitR@1.0.2
#: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=ConduitR&version=1.0.2
#tool nuget:?package=ConduitR&version=1.0.2
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
ConduitR
Lightweight, fast, and familiar mediator for .NET — designed to feel natural for MediatR users, with a focus on performance, simplicity, and great DX.
Why ConduitR?
- Familiar: same mental model as MediatR (
IRequest<T>
,IRequestHandler
, notifications, behaviors). - Fast: hot path optimized (cached pipelines per request type, low allocations, ValueTask).
- Modular: add-on packages for Validation, AspNetCore helpers, Processing, and Resilience (Polly).
- Observable: built-in
ActivitySource
for OpenTelemetry (Send
,Publish
,Stream
).
Packages
Package | What it adds |
---|---|
ConduitR |
Core mediator + telemetry |
ConduitR.Abstractions |
Public contracts (requests, handlers, behaviors, etc.) |
ConduitR.DependencyInjection |
AddConduit(...) + assembly scanning |
ConduitR.Validation.FluentValidation |
Validation behavior + DI helpers (optional) |
ConduitR.AspNetCore |
ProblemDetails middleware + Minimal API helpers (optional) |
ConduitR.Processing |
Pre/Post processors as behaviors (optional) |
ConduitR.Resilience.Polly |
Retry / Timeout / CircuitBreaker behaviors (optional) |
Install
dotnet add package ConduitR
dotnet add package ConduitR.Abstractions
dotnet add package ConduitR.DependencyInjection
# Optional add-ons
dotnet add package ConduitR.Validation.FluentValidation
dotnet add package ConduitR.AspNetCore
dotnet add package ConduitR.Processing
dotnet add package ConduitR.Resilience.Polly
Quick start
// Program.cs
using System.Reflection;
using ConduitR;
using ConduitR.Abstractions;
using ConduitR.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddConduit(cfg =>
{
cfg.AddHandlersFromAssemblies(Assembly.GetExecutingAssembly());
cfg.PublishStrategy = PublishStrategy.Parallel; // Parallel (default), Sequential, StopOnFirstException
});
var app = builder.Build();
app.Run();
// A request + handler
public sealed record Ping(string Name) : IRequest<string>;
public sealed class PingHandler : IRequestHandler<Ping, string>
{
public ValueTask<string> Handle(Ping request, CancellationToken ct)
=> ValueTask.FromResult($"Hello, {request.Name}!");
}
Use the mediator anywhere (DI):
var result = await mediator.Send(new Ping("ConduitR"));
Notifications (Publish)
public sealed record UserRegistered(string Email) : INotification;
public sealed class SendWelcomeEmail : INotificationHandler<UserRegistered> { /* ... */ }
public sealed class AuditLog : INotificationHandler<UserRegistered> { /* ... */ }
// Strategy via AddConduit(...):
// Parallel (default), Sequential (aggregate errors), StopOnFirstException (short-circuit)
await mediator.Publish(new UserRegistered("x@y.com"));
Streaming
public sealed record Ticks(int Count) : IStreamRequest<string>;
public sealed class TicksHandler : IStreamRequestHandler<Ticks, string>
{
public async IAsyncEnumerable<string> Handle(Ticks req, [EnumeratorCancellation] CancellationToken ct)
{
for (var i = 1; i <= req.Count; i++) { ct.ThrowIfCancellationRequested(); await Task.Delay(100, ct); yield return $"tick-{i}"; }
}
}
// Consume
await foreach (var s in mediator.CreateStream(new Ticks(3))) Console.WriteLine(s);
Validation (FluentValidation)
using ConduitR.Validation.FluentValidation;
builder.Services.AddConduitValidation(typeof(Program).Assembly);
public sealed record CreateOrder(string? Sku, int Qty) : IRequest<string>;
public sealed class CreateOrderValidator : AbstractValidator<CreateOrder>
{
public CreateOrderValidator() { RuleFor(x => x.Sku).NotEmpty(); RuleFor(x => x.Qty).GreaterThan(0); }
}
AspNetCore helpers
using ConduitR.AspNetCore;
// ProblemDetails (400s for validation, 5xx handled)
builder.Services.AddConduitProblemDetails();
var app = builder.Build();
app.UseConduitProblemDetails();
// Minimal API mapper
app.MapMediatorPost<CreateOrder, string>("/orders");
Pre/Post processors
using ConduitR.Processing;
builder.Services.AddConduitProcessing(typeof(Program).Assembly);
public sealed class AuditPre : IRequestPreProcessor<CreateOrder>
{
public Task Process(CreateOrder req, CancellationToken ct) { /* audit */ return Task.CompletedTask; }
}
public sealed class MetricsPost : IRequestPostProcessor<CreateOrder, string>
{
public Task Process(CreateOrder req, string res, CancellationToken ct) { /* metrics */ return Task.CompletedTask; }
}
Resilience (Polly)
using ConduitR.Resilience.Polly;
builder.Services.AddConduitResiliencePolly(o =>
{
o.RetryCount = 3; // exponential backoff
o.Timeout = TimeSpan.FromSeconds(1); // per-attempt timeout (pessimistic)
o.CircuitBreakerEnabled = true;
o.CircuitBreakerFailures = 5;
o.CircuitBreakerDuration = TimeSpan.FromSeconds(30);
});
Telemetry (OpenTelemetry)
using ConduitR;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
builder.Services.AddOpenTelemetry()
.ConfigureResource(r => r.AddService("YourApp"))
.WithTracing(b => b
.AddSource(ConduitRTelemetry.ActivitySourceName) // "ConduitR"
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter());
Spans: Mediator.Send
, Mediator.Publish
, Mediator.Stream
(+ tags & exception events).
Performance
- Cached Send/Stream pipelines per
(TRequest,TResponse)
(no per-call reflection/delegate build). - Lean publish path, minimal allocations.
ValueTask
in core, one-type-per-file organization.
See docs/perf-pipeline-cache.md
for details.
Migrate from MediatR
MediatR | ConduitR |
---|---|
IMediator.Send , .Publish |
same |
IRequest<TResponse> |
same |
IRequestHandler<TReq,TRes> |
same |
INotification , INotificationHandler<T> |
same |
Pipeline behaviors | same (IPipelineBehavior<TReq,TRes> ) |
Pre/Post processors | via ConduitR.Processing (behaviors) |
Validation (FluentValidation) | ConduitR.Validation.FluentValidation |
ASP.NET Core helpers | ConduitR.AspNetCore |
Resilience | ConduitR.Resilience.Polly |
Samples
samples/Samples.WebApi
— minimal API, ProblemDetails, validation, and streaming endpoint.
Versioning & Releases
- Semantic versioning. Latest stable: 1.0.2
- See GitHub Releases for notes.
Contributing
PRs welcome! Dev loop:
dotnet restore
dotnet build
dotnet test
(Optional) microbenchmarks:
dotnet run -c Release --project benchmarks/ConduitR.Benchmarks/ConduitR.Benchmarks.csproj
License
MIT — see LICENSE.
Commit it
git add README.md
git commit -m "docs: refresh README with streaming, publish strategies, processing, resilience, telemetry, perf"
git push
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. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net8.0
- ConduitR.Abstractions (>= 1.0.2)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ConduitR:
Package | Downloads |
---|---|
ConduitR.DependencyInjection
Microsoft.Extensions.DependencyInjection integration for ConduitR. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
1.0.3-pre.20250814T0249... | 112 | 8/14/2025 |
1.0.3-pre.20250813T2211... | 114 | 8/13/2025 |
1.0.3-pre.20250813T2207... | 111 | 8/13/2025 |
1.0.2 | 133 | 8/13/2025 |
1.0.2-pre.20250813T2202... | 112 | 8/13/2025 |
1.0.2-pre.20250813T2144... | 113 | 8/13/2025 |
1.0.2-pre.20250813T2132... | 113 | 8/13/2025 |
1.0.2-pre.20250813T2115... | 112 | 8/13/2025 |
1.0.2-pre.20250813T2108... | 119 | 8/13/2025 |
1.0.2-pre.20250813T2059... | 113 | 8/13/2025 |
1.0.2-pre.20250813T2058... | 110 | 8/13/2025 |
1.0.2-pre.20250813T2034... | 109 | 8/13/2025 |
1.0.2-pre.20250813T2025... | 112 | 8/13/2025 |
1.0.1 | 119 | 8/13/2025 |
1.0.0 | 122 | 8/13/2025 |
0.1.0-pre.20250813T2021... | 111 | 8/13/2025 |
0.1.0-pre.20250813T2005... | 112 | 8/13/2025 |
0.1.0-pre.20250813T2001... | 114 | 8/13/2025 |
0.1.0-pre.20250813T1905... | 113 | 8/13/2025 |
0.1.0-pre.20250813T1849... | 118 | 8/13/2025 |
0.1.0-pre.20250813T1847... | 115 | 8/13/2025 |
0.1.0-pre.20250813T1839... | 117 | 8/13/2025 |