Advanced Usage
9.3.1. CancellationToken Support
v1.27.0 — When a service method declares CancellationToken cancellationToken = default, SmartEndpoints detects it and injects the cancellation token through the generated lambda automatically. Methods without this parameter are unaffected — fully backward-compatible.
[AutoGenerateEndpoints(RoutePrefix = "/api/users")]
public class UserController
{
// CancellationToken detected — generator threads it through
public async Task<Result<User>> GetUser(int id, CancellationToken cancellationToken = default)
=> await _service.GetByIdAsync(id, cancellationToken);
// No CancellationToken — generated normally, no change
public async Task<Result<List<User>>> GetUsers()
=> await _service.GetAllAsync();
}
Generated lambdas (v1.27.0+):
// With CancellationToken — ct injected by ASP.NET Minimal API
userGroup.MapGet("/{id}", async (int id, UserController service, CancellationToken ct) =>
{
var result = await service.GetUser(id, ct);
return result.ToIResult();
});
// Without CancellationToken — unchanged
userGroup.MapGet("", async (UserController service) =>
{
var result = await service.GetUsers();
return result.ToIResult();
});
9.3.2. FluentValidation Bridge
⚠️ Optional — migration bridge only. Not needed for new projects.
REslava.Result already includes full native validation via
[Validate](DataAnnotations →Result<T>) and the Validation DSL (19 fluent rules). This package exists only for teams that already have FluentValidation validators and want to adopt REslava.Result without rewriting them. New projects should use[Validate]or the Validation DSL instead.
v1.28.0 — For teams migrating from FluentValidation, the REslava.Result.FluentValidation package emits .Validate(IValidator<T>) extensions and integrates with SmartEndpoints — existing validators require zero changes:
dotnet add package REslava.Result.FluentValidation
dotnet add package FluentValidation # your existing validators
using REslava.Result.FluentValidation;
[FluentValidate] // ← swap [Validate] for [FluentValidate] on existing FV types
public record CreateOrderRequest(string CustomerId, decimal Amount);
// Your AbstractValidator<T> stays unchanged
public class CreateOrderRequestValidator : AbstractValidator<CreateOrderRequest>
{
public CreateOrderRequestValidator()
{
RuleFor(x => x.CustomerId).NotEmpty();
RuleFor(x => x.Amount).GreaterThan(0);
}
}
Generated lambda (v1.28.0+):
ordersGroup.MapPost("", async (
CreateOrderRequest req,
IValidator<CreateOrderRequest> reqValidator, // ← auto-injected from DI
IOrderService svc,
CancellationToken cancellationToken) =>
{
var validation = req.Validate(reqValidator); // ← uses FluentValidation internally
if (!validation.IsSuccess) return validation.ToIResult();
var result = await svc.CreateOrder(req, cancellationToken);
return result.ToIResult();
});
Register in DI once — SmartEndpoints handles the rest:
builder.Services.AddScoped<IValidator<CreateOrderRequest>, CreateOrderRequestValidator>();
> Note: [FluentValidate] and [Validate] cannot be applied to the same type (RESL1006 compile error). Choose the bridge for existing FV validators; use [Validate] for new types with DataAnnotations.