Skip to content

ZibStack.NET.Validation — Alternatives

Validation in .NET splits into two worlds: attributes on properties (DataAnnotations — built in, limited), and fluent code (FluentValidation — flexible, runtime). ZibStack.NET.Validation combines the ergonomics of attributes (stay on the DTO where the fields are) with the performance of a source generator (compile-time, zero reflection, TryValidate / Validate methods generated directly on the type).

FeatureZibStack.NET.ValidationDataAnnotationsFluentValidation
Rule locationAttributes on properties ([ZRequired], [ZRange], [ZEmail], [ZNotEmpty], …)Attributes on propertiesSeparate AbstractValidator<T> class
Rule evaluationGenerated method body at compile timeRuntime reflection (Validator.TryValidateObject)Compiled expression trees (runtime)
Reflection on hot path❌ zero✅ yespartial
AOT-friendly✅ no reflection, no expressionspartial (some attributes reflect)❌ expression trees
Custom rules[ZMatch(pattern)] + ValidationAttribute subclass still worksValidationAttribute subclassMust(x => …) / custom validator
Conditional rulespartial (via [Required] + NRT) — plain conditional via custom attributeWhen(x => …)
Async rules❌ (source gen can’t emit await — out of scope)MustAsync
Multiple errors returnedValidationResult.ErrorsValidationResult[]ValidationResult.Errors
ASP.NET Core auto-integration✅ runs via ProblemDetails or [Dto] endpoints✅ built-in⚠️ FluentValidation.AspNetCore deprecated in v12
DTO / TS / OpenAPI cross-target consistency✅ picked up by ZibStack.NET.TypeGen → OpenAPI minLength, pattern, Zod .email(), .gte()n/an/a
Install footprintNuGet (source gen only, no runtime lib)zero (BCL)NuGet

Async validation and richly conditional rules (.When(...).Otherwise(...)) — FluentValidation still wins when your rule needs to hit a database (MustAsync(async x => await repo.ExistsAsync(x))). Source-generated validation intentionally stays synchronous + expression-free.

You want the ergonomic simplicity of DataAnnotations (rules live on the property, one-liner) plus zero-reflection performance plus the rules flow automatically to your OpenAPI / Zod / TypeScript contracts via ZibStack.NET.TypeGen. No separate validator class to keep in sync with the DTO, no runtime cost that shows up on hot paths or in AOT builds.

  • FluentValidation — you need async rules (DB lookups, external service calls), complex cross-field conditionals, or your team already has a large validator library invested.
  • DataAnnotations vanilla — tiny app, one-off validation, don’t care about perf, don’t need cross-target contract generation.