Skip to main content

Configuration

Dispatch uses the standard .NET configuration patterns with fluent builders for service registration.

Before You Start

Basic Configuration

Service Registration

Register Dispatch in your Program.cs:

var builder = WebApplication.CreateBuilder(args);

// Auto-discover handlers from an assembly (recommended)
builder.Services.AddDispatch(dispatch =>
{
dispatch.AddHandlersFromAssembly(typeof(Program).Assembly);
});

var app = builder.Build();

Configuration Flow

flowchart TD
A[Program.cs] --> B[AddDispatch]
B --> C[IDispatchBuilder]
C --> D[Handler Registration]
C --> E[Middleware Configuration]
C --> F[Pipeline Profiles]
C --> G[Transport Setup]

Using the Dispatch Builder

The main configuration method uses a fluent builder for comprehensive setup:

// Register handlers from assembly with configuration
builder.Services.AddDispatch(dispatch =>
{
// Handler registration
dispatch.AddHandlersFromAssembly(typeof(Program).Assembly);

// Global middleware
dispatch.UseMiddleware<LoggingMiddleware>();
dispatch.UseMiddleware<ValidationMiddleware>();

// Options configuration
dispatch.ConfigureOptions<DispatchOptions>(options =>
{
options.DefaultTimeout = TimeSpan.FromSeconds(30);
});
});

// Serialization: JSON (System.Text.Json) is the default with AddDispatch().
// For binary serialization, install the provider package and register:
// services.AddMemoryPackSerializer();
// services.AddMessagePackSerializer();

Handler Registration

// Single assembly (recommended)
builder.Services.AddDispatch(dispatch =>
{
dispatch.AddHandlersFromAssembly(typeof(Program).Assembly);
});

// Multiple assemblies
builder.Services.AddDispatch(dispatch =>
{
dispatch.AddHandlersFromAssembly(typeof(OrderHandler).Assembly);
dispatch.AddHandlersFromAssembly(typeof(PaymentHandler).Assembly);
});

Middleware Configuration

builder.Services.AddDispatch(dispatch =>
{
dispatch.AddHandlersFromAssembly(typeof(Program).Assembly);

// Add global middleware (applies to all pipelines)
dispatch.UseMiddleware<LoggingMiddleware>();

// Or configure a named pipeline with specific middleware
dispatch.ConfigurePipeline("Actions", pipeline =>
{
pipeline.ForMessageKinds(MessageKinds.Action)
.Use<ValidationMiddleware>()
.Use<AuthorizationMiddleware>();
});

dispatch.ConfigurePipeline("Events", pipeline =>
{
pipeline.ForMessageKinds(MessageKinds.Event);
});
});
Automatic Default Pipeline

When you use UseMiddleware<T>() without explicitly calling ConfigurePipeline(), Dispatch automatically creates a "Default" pipeline containing your global middleware. This means you don't need to configure pipelines for simple scenarios—your middleware is applied to all messages automatically.

Options Configuration

builder.Services.AddDispatch(dispatch =>
{
dispatch.AddHandlersFromAssembly(typeof(Program).Assembly);

// Configure dispatch options
dispatch.ConfigureOptions<DispatchOptions>(options =>
{
options.DefaultTimeout = TimeSpan.FromSeconds(30);
});
});

Ultra-Local Performance Options

Configure direct-local/ultra-local behavior on DispatchOptions.CrossCutting.Performance:

builder.Services.AddDispatch(dispatch =>
{
dispatch.AddHandlersFromAssembly(typeof(Program).Assembly);
dispatch.ConfigureOptions<DispatchOptions>(options =>
{
options.CrossCutting.Performance.DirectLocalContextInitialization =
DirectLocalContextInitializationProfile.Lean; // default

options.CrossCutting.Performance.EmitDirectLocalResultMetadata = false; // default
});
});

Use DirectLocalContextInitializationProfile.Full when you need eager full-context initialization on direct-local paths.

See Ultra-Local Dispatch for dispatch semantics and fallback behavior.

Profile detail:

ProfileDirect-local initialization behavior
Lean (default)Sets Message, correlation/causation (when needed), and skips eager MessageType population
FullSame as Lean, plus eager MessageType initialization when missing

Cross-Cutting Concerns

Configure observability, resilience, caching, and security through the builder:

builder.Services.AddDispatch(dispatch =>
{
dispatch.AddHandlersFromAssembly(typeof(Program).Assembly);

// Observability (tracing, metrics, context flow)
dispatch.UseObservability();

// Resilience (retry, circuit breaker, timeout)
dispatch.UseResilience(res => res.DefaultRetryCount = 3);

// Caching
dispatch.UseCaching();

// Security (requires IConfiguration for reflection-based scanning)
dispatch.UseSecurity(builder.Configuration);
});
Short names on the builder

When called on IDispatchBuilder, the Dispatch prefix is dropped since it's redundant. For example, services.AddDispatchObservability() becomes dispatch.UseObservability().

What's Next

See Also

  • Built-in Middleware -- Pre-built middleware for logging, validation, authorization, and more
  • Getting Started -- Step-by-step guide to setting up your first Dispatch project
  • Transports -- Transport-specific configuration