Skip to main content

Handler Integration

ResilienceBehavior<TRequest, TResponse> intercepts every request dispatched through Vali-Mediator and automatically wraps handler execution with the resolved policy — no changes needed in the handler itself.

How It Works

loading...

Registration

builder.Services.AddValiMediator(config =>
{
config.RegisterServicesFromAssemblyContaining<Program>();
config.AddResilienceBehavior();
});

The preferred way to attach a policy is via AddResiliencePolicy<T> or IResiliencePolicyProvider<TRequest>. This keeps the command clean — no infrastructure properties mixed into the domain model.

See Policy Providers for the full guide.

// Command — pure domain data, no policy property
public class PlaceOrderCommand : IRequest<Result<string>>
{
public string OrderId { get; init; } = string.Empty;
public decimal Amount { get; init; }
}

// Policy registered at startup
services.AddResiliencePolicy<PlaceOrderCommand>(_ =>
ResiliencePolicy.Create("place-order")
.Retry(3)
.CircuitBreaker(opts =>
{
opts.CircuitKey = "payment-gateway";
opts.FailureThreshold = 5;
opts.BreakDuration = TimeSpan.FromSeconds(30);
})
.Timeout(TimeSpan.FromSeconds(10))
.Build());

Deprecated: IResilient on the Command

Deprecated in v1.2.0

IResilient is kept for backward compatibility but should not be used in new code. Putting a ResiliencePolicy property on the command mixes infrastructure with domain data — the policy object gets serialized alongside command fields. Use services.AddResiliencePolicy<T>() instead.

// ❌ Old approach — policy lives on the command
[Obsolete]
public class CallPaymentGatewayCommand : IRequest<Result<PaymentDto>>, IResilient
{
public string OrderId { get; init; } = string.Empty;

private static readonly ResiliencePolicy _policy = ResiliencePolicy
.Create("payment-gateway")
.Retry(3)
.Timeout(TimeSpan.FromSeconds(10))
.Build();

public ResiliencePolicy Policy => _policy;
}
// ✅ New approach — policy separate from the command
public class CallPaymentGatewayCommand : IRequest<Result<PaymentDto>>
{
public string OrderId { get; init; } = string.Empty;
}

services.AddResiliencePolicy<CallPaymentGatewayCommand>(_ =>
ResiliencePolicy.Create("payment-gateway")
.Retry(3)
.Timeout(TimeSpan.FromSeconds(10))
.Build());

Policy Resolution Order

PriorityMechanism
1AddResiliencePolicy<T> / AddResiliencePolicyProvider<T,P>
2IResilient on the command (deprecated)
3AddGlobalResiliencePolicy
No policy → request passes through as-is