ZeroAlloc.Validation.AspNetCore
2.3.3
dotnet add package ZeroAlloc.Validation.AspNetCore --version 2.3.3
NuGet\Install-Package ZeroAlloc.Validation.AspNetCore -Version 2.3.3
<PackageReference Include="ZeroAlloc.Validation.AspNetCore" Version="2.3.3" />
<PackageVersion Include="ZeroAlloc.Validation.AspNetCore" Version="2.3.3" />
<PackageReference Include="ZeroAlloc.Validation.AspNetCore" />
paket add ZeroAlloc.Validation.AspNetCore --version 2.3.3
#r "nuget: ZeroAlloc.Validation.AspNetCore, 2.3.3"
#:package ZeroAlloc.Validation.AspNetCore@2.3.3
#addin nuget:?package=ZeroAlloc.Validation.AspNetCore&version=2.3.3
#tool nuget:?package=ZeroAlloc.Validation.AspNetCore&version=2.3.3
ZeroAlloc.Validation
Source-generated, attribute-based alternative to FluentValidation for .NET: no reflection, 0 bytes allocated when a model is valid, and NativeAOT-ready.
Why ZeroAlloc.Validation
- Nothing allocated on the valid path. A passing validation allocates 0 B, asserted by allocation regression tests for flat, nested and collection models. FluentValidation 12 allocates 696–3,528 B for the same models.
- 27.8–133.2× faster than FluentValidation 12 on the valid path, measured side by side in the same BenchmarkDotNet run.
- Works under NativeAOT and trimming. The validator is plain generated C#, with no reflection or expression trees; CI publishes and runs a NativeAOT sample on every build.
- Mistakes surface at compile time. A numeric rule on a string, an
[IsInEnum]on a non-enum or a[CustomValidation]method with the wrong signature fails the build, not a request.
Install
dotnet add package ZeroAlloc.Validation
The source generator ships inside this package; nothing else is required.
Quick start
using System;
using ZeroAlloc.Validation;
var validator = new CreateOrderRequestValidator(); // generated at build time
var result = validator.Validate(new CreateOrderRequest { Reference = "", Amount = 0, Email = "nope" });
if (!result.IsValid)
foreach (ref readonly var f in result.Failures)
Console.WriteLine($"{f.PropertyName}: {f.ErrorMessage}");
[Validate]
public class CreateOrderRequest
{
[NotEmpty, MaxLength(50)] public string Reference { get; set; } = "";
[GreaterThan(0)] public decimal Amount { get; set; }
[NotEmpty, EmailAddress] public string Email { get; set; } = "";
}
Mark a model with [Validate] and the generator writes CreateOrderRequestValidator for you. Running it prints:
Reference: Reference must not be empty.
Amount: Amount must be greater than 0.
Email: Email must be a valid email address.
What you get
- 20 built-in rules as attributes: emptiness, equality, ranges, lengths, regex, e-mail, enums, precision and scale.
- Your own rules through reusable attributes, inline
[Must]predicates or[CustomValidation]methods. - Asynchronous rules, awaited by the generated
ValidateAsync. - Nested objects and collections, with property paths such as
Items[0].Skuin the failures. - Rules inherited from base types, conditional rules with
When,Unlessand[SkipWhen], and short-circuiting with[StopOnFirstFailure]. - Per-rule severity,
Error,WarningorInfo, and custom error messages with placeholders. - Pipeline behaviors that wrap validation calls, without a per-call allocation.
Optional packages:
ZeroAlloc.Validation.AspNetCore: validates request models automatically and returns HTTP 422 on failure.ZeroAlloc.Validation.Inject: registers every validator in DI with oneAddZeroAllocValidators()call.ZeroAlloc.Validation.Options: validatesMicrosoft.Extensions.Optionsat startup withValidateWithZeroAlloc().ZeroAlloc.Validation.Testing: fluent assertions for unit-testing validators.
Performance
| Scenario | Speedup vs FluentValidation 12 | Allocated (valid) |
|---|---|---|
| Flat model | 27.8× | 0 B vs 696 B |
| Nested model | 133.2× | 0 B vs 1,488 B |
| Collection, 3 items | 91.7× | 0 B vs 3,528 B |
Valid path, FluentValidation 12.1.1, measured 2026-10-15. Allocations are exact. Speed is shown as same-run ratios, because the benchmark host is a shared VM; absolute timings are not published. On the invalid path ZeroAlloc is 12.7–62.9× faster and allocates 12.4–74.9× less. See Performance for the full results.
Learn more
- Documentation: validation.zeroalloc.net, including the attribute reference and the diagnostics list.
- Upgrading from v1: Migrating to v2 and the changelog.
Related ZeroAlloc packages:
- ZeroAlloc.Mediator (docs): its
ZeroAlloc.Mediator.Validationpackage runs these validators on every request before the handler. - ZeroAlloc.Results (docs): a Mediator request that returns
Result<T, ValidationError>gets a failed validation back as a failure result, not an exception. - ZeroAlloc.Pipeline (docs): the pipeline-behavior model this library's validator behaviors are built on.
- ZeroAlloc.Authorization (docs): plugs into the same Mediator pipeline and runs before validation, so a denied caller sees no validation errors.
Contributions are welcome: open an issue or a pull request. Licensed under MIT.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- ZeroAlloc.Validation (>= 2.3.3)
-
net8.0
- ZeroAlloc.Validation (>= 2.3.3)
-
net9.0
- ZeroAlloc.Validation (>= 2.3.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.3.3 | 53 | 10/16/2026 |
| 2.3.2 | 51 | 10/15/2026 |
| 2.3.1 | 126 | 10/12/2026 |
| 2.3.0 | 94 | 10/11/2026 |
| 2.2.1 | 89 | 10/11/2026 |
| 2.2.0 | 92 | 10/10/2026 |
| 2.1.0 | 114 | 9/30/2026 |
| 2.0.3 | 202 | 9/30/2026 |
| 2.0.2 | 113 | 9/28/2026 |
| 2.0.1 | 107 | 9/27/2026 |
| 2.0.0 | 139 | 9/26/2026 |
| 1.7.8 | 236 | 9/24/2026 |
| 1.7.7 | 98 | 9/24/2026 |
| 1.7.6 | 102 | 9/24/2026 |
| 1.7.5 | 120 | 9/21/2026 |
| 1.7.4 | 94 | 9/20/2026 |
| 1.7.3 | 95 | 9/20/2026 |
| 1.7.2 | 97 | 9/20/2026 |
| 1.7.1 | 112 | 9/19/2026 |
| 1.7.0 | 109 | 9/12/2026 |