ValidationModules.Runtime 0.1.0-alpha.1

This is a prerelease version of ValidationModules.Runtime.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package ValidationModules.Runtime --version 0.1.0-alpha.1
                    
NuGet\Install-Package ValidationModules.Runtime -Version 0.1.0-alpha.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ValidationModules.Runtime" Version="0.1.0-alpha.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ValidationModules.Runtime" Version="0.1.0-alpha.1" />
                    
Directory.Packages.props
<PackageReference Include="ValidationModules.Runtime" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ValidationModules.Runtime --version 0.1.0-alpha.1
                    
#r "nuget: ValidationModules.Runtime, 0.1.0-alpha.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ValidationModules.Runtime@0.1.0-alpha.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ValidationModules.Runtime&version=0.1.0-alpha.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=ValidationModules.Runtime&version=0.1.0-alpha.1&prerelease
                    
Install as a Cake Tool

ValidationModules

Compile-time validation for .NET. Rules are declared as attributes and flattened into straight-line C# by a source generator at build time. No reflection, no expression trees, no regex compiled at runtime — Native AOT is a hard requirement rather than a supported configuration.

public record Pet {
    [Required]
    [StringLength(min: 1, max: 100)]
    public string Name { get; init; }

    [Pattern("^[a-zA-Z0-9-]*$")]
    public string? Sku { get; init; }

    [ValidateNested]
    public Address? Home { get; init; }

    [ItemCount(min: 1, max: 10), ValidateNested]
    public IReadOnlyList<Toy> Toys { get; init; } = [];
}
var result = validator.Validate(pet);

foreach (var error in result.Errors) {
    Console.WriteLine($"{error.Field}: {error.Code}");
}
// name             required
// home.postalCode  required
// toys[3].name     required

Why

FluentValidation compiles expression trees at runtime. Under Native AOT Expression.Compile() falls back to the LINQ interpreter rather than throwing, so it works — but property access is interpreted and you carry IL2026/IL3050 trim warnings. For a workload where AOT is a requirement, that is the gap this fills.

ValidationModules.Runtime carries IsAotCompatible and escalates IL2026;IL2055;IL2067;IL2072; IL2075;IL2087;IL3050 to errors, so the constraint is enforced by the compiler rather than by review.

Status

Pre-1.0, and under construction. Built so far:

Stage
1 Runtime — contracts, context, error model, constraint attributes, naming done
2 Generator, no profiles done
3 Profiles not started
4 Impl packaging for framework authors done
5 Hardened integration substantially done
6 FluentValidation adapter and conformance suite not started

Also built since the plan was written, and not in its staging: a declarative rule-class front end (IValidationRulesFor<T>, API-SURFACE.md §19) and a DataAnnotations front end (§18).

Two known gaps remain:

  • Profiles are not built, and their declaration surface shipped ahead of them — FromProfile/UntilProfile/Profiles on every constraint, and IValidationProfile in the runtime. Using one is VM0019, an error, because the arguments are ignored rather than inert: a rule written to apply only from V2 would be enforced under V1 as well. Removing that diagnostic is the first thing Stage 3 does.
  • VM0007 is declared and never reported. [ValidateNested] on a type with no rules of its own descends into nothing and says nothing. DiagnosticCatalogueTests records it as the one dead descriptor and fails in both directions.

Documentation

The docs site lives in website/ and publishes to https://ipjohnson.github.io/ValidationModules/:

cd website && npm install && npm run dev

Dead internal links fail the build, so a rename cannot rot a link silently.

Design

  • IMPLEMENTATION-PLAN.md — what is being built and why. A specification, not a discussion document.
  • API-SURFACE.md — the exact public surface, the reasoning behind each decision, and the verification log behind the claims.

The single most consequential decision is in API-SURFACE.md §13.1: ValidationContext is a readonly struct rather than a ref struct, carrying its own path rather than indexing into shared storage. That is what lets IAsyncValidatorFor<T> take the same context as the synchronous side, and what makes a context safe to hold across an await or hand to a concurrent branch.

Packages

Package Ships as Referenced by
ValidationModules.Runtime lib/ application code
ValidationModules.SourceGenerator analyzers/dotnet/cs application code, PrivateAssets=all
ValidationModules.SourceGenerator.Impl source-only framework authors
ValidationModules.FluentValidation lib/ optional adapter
ValidationModules.Testing lib/ conformance suite

ValidationModules.Runtime depends only on Microsoft.Extensions.DependencyInjection.Abstractions, framework-matched per TFM. It does not reference DependencyModules.Runtime — the library is DependencyModules-shaped in its ergonomics, but only the generated module needs DM types, and that lands in the consumer's assembly, which already references DM.

Building

dotnet build --configuration Release
dotnet test  --configuration Release
dotnet test  --configuration Release --collect:"XPlat Code Coverage" --settings coverlet.runsettings

The public API is pinned by a snapshot at tests/ValidationModules.Runtime.Tests/Snapshots/PublicApiTests.RuntimeApi.verified.txt — one file listing every public type and member, which is also the quickest way to read the surface. To accept an intended change:

UPDATE_SNAPSHOTS=1 dotnet test tests/ValidationModules.Runtime.Tests

Benchmarks

./scripts/benchmark.sh                     # ValidationModules alone, JIT and Native AOT
./scripts/benchmark.sh --quick             # the same, fast enough to run after a change
./scripts/benchmark.sh --comparative       # against FluentValidation and DataAnnotations

Two suites. The default one measures this library on its own and is what a change should be checked against; the comparative one is opt-in, because its numbers move when FluentValidation changes as well as when this does. benchmarks/README.md covers what each measures, and the four choices the comparative suite makes in FluentValidation's favour so the comparison stays honest.

License

MIT.

Product 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 was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on ValidationModules.Runtime:

Package Downloads
Hardened.Requests.Runtime

Execution pipeline implementation for Hardened: filters, serialization, parameter validation and error handling.

ValidationModules.AspNetCore

ASP.NET Core integration for ValidationModules: an endpoint filter that validates minimal API arguments before the handler runs, an RFC 9457 ProblemDetails mapping for ValidationResult, and an exception handler for ValidationException. No reflection, Native AOT safe.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-rc1006 162 8/16/2026
1.0.0-rc1005 54 8/16/2026
1.0.0-rc1004 52 8/16/2026
1.0.0-rc1003 188 8/14/2026
1.0.0-rc1002 55 8/14/2026
0.1.0-alpha.1 106 8/13/2026