- Add path-specific rules for commands/queries, dynamic queries, validation, and gRPC - Add /add-command, /add-query, /add-dynamic-query scaffolding skills - Add project settings with post-edit formatting, proto validation, and build-gate hooks - Add .editorconfig codifying existing code style conventions - Trim CLAUDE.md from 414 to 130 lines (domain details moved to rules) - Add .harness-version tracking for the shared claude-harness repo Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1.9 KiB
1.9 KiB
| paths | ||
|---|---|---|
|
FluentValidation Integration
Validator Pattern
Validators live in the same file as their command/query, named {CommandName}Validator:
public class PlaceOrderCommandValidator : AbstractValidator<PlaceOrderCommand>
{
public PlaceOrderCommandValidator()
{
RuleFor(x => x.CustomerId)
.NotEmpty()
.WithMessage("Customer is required");
RuleFor(x => x.Items)
.NotEmpty()
.WithMessage("At least one item is required");
}
}
Registration
Validators are registered alongside their handler using the FluentValidation overloads:
// Command without result + validator
services.AddCommand<DeactivateAccountCommand, DeactivateAccountCommandHandler, DeactivateAccountCommandValidator>();
// Command with result + validator
services.AddCommand<PlaceOrderCommand, int, PlaceOrderCommandHandler, PlaceOrderCommandValidator>();
// Query + validator
services.AddQuery<FetchOrderByIdQuery, Order, FetchOrderByIdQueryHandler, FetchOrderByIdQueryValidator>();
These come from Svrnty.CQRS.FluentValidation.ServiceCollectionExtensions — they call the base AddCommand/AddQuery then register IValidator<T>.
Error Formats by Protocol
The framework handles validation execution automatically. Errors are returned as:
- HTTP (Minimal API): RFC 7807 Problem Details —
400 Bad Requestwith structured error body - gRPC: Google Rich Error Model —
google.rpc.StatuswithBadRequestdetail containingFieldViolations
You do NOT need to manually invoke validation in handlers. The endpoint layer (Minimal API or gRPC source-generated service) handles it.
Rules
- Inherit from
AbstractValidator<T>, notIValidator<T>directly - Define all rules in the constructor
- Always include
.WithMessage()for user-facing error messages - Validator constructor can inject services for async/database validation