ValidationModules.AspNetCore
1.2.0
dotnet add package ValidationModules.AspNetCore --version 1.2.0
NuGet\Install-Package ValidationModules.AspNetCore -Version 1.2.0
<PackageReference Include="ValidationModules.AspNetCore" Version="1.2.0" />
<PackageVersion Include="ValidationModules.AspNetCore" Version="1.2.0" />
<PackageReference Include="ValidationModules.AspNetCore" />
paket add ValidationModules.AspNetCore --version 1.2.0
#r "nuget: ValidationModules.AspNetCore, 1.2.0"
#:package ValidationModules.AspNetCore@1.2.0
#addin nuget:?package=ValidationModules.AspNetCore&version=1.2.0
#tool nuget:?package=ValidationModules.AspNetCore&version=1.2.0
ValidationModules
ValidationModules writes the validators for your .NET types at build time. You declare rules with attributes on a model, or in a rules class. A source generator turns them into a validator class made of ordinary C# checks. The validators read members directly instead of through reflection, so they work in trimmed and Native AOT applications.
Documentation: https://ipjohnson.github.io/ValidationModules/
Install
dotnet add package ValidationModules.Runtime
dotnet add package ValidationModules.SourceGenerator
The runtime targets .NET 8 and .NET 10.
Example
using ValidationModules.Constraints;
public sealed class SignUp
{
[Required, EmailAddress]
public string? Email { get; init; }
[Required, StringLength(40, Min = 3)]
public string? DisplayName { get; init; }
[Range(18, 120)]
public int Age { get; init; }
}
The generator writes a class named SignUpValidator that checks these rules. It also writes one
extension method that registers every validator in the project. The method is named after the
assembly, so a project named Shop gets AddShopValidators().
using Microsoft.Extensions.DependencyInjection;
using ValidationModules;
var services = new ServiceCollection();
services.AddShopValidators();
using var provider = services.BuildServiceProvider();
var validator = provider.GetRequiredService<IValidatorFor<SignUp>>();
var result = validator.Validate(
new SignUp
{
Email = "not-an-email",
DisplayName = "",
Age = 12,
}
);
foreach (var error in result.Errors)
{
Console.WriteLine($"{error.Field}: {error.Code}: {error.Message}");
}
email: email: email is not a valid email address.
displayName: required: displayName is required.
age: range: age must be between 18 and 120.
Every error has a Field path, a Code, a Message, and a Severity. The codes are stable, so
application logic and translations should key on Code rather than on the message text.
Rules that span members
An attribute sees one member. A rules class can compare several:
using ValidationModules;
public sealed class BookingRules : IValidationRulesFor<Booking>
{
public static void Describe(ValidationRules<Booking> rules, Booking x)
{
rules.Require(x.Guest).Length(1, 80);
rules.Range(x.Guests, 1, 8);
rules.Ensure(x.End > x.Start, message: "The stay must end after it starts.");
}
}
The generator reads Describe at build time and writes its rules into BookingValidator. The
method itself is never called.
Compared with DataAnnotations
- Most attributes share their names with
System.ComponentModel.DataAnnotations, such as[Required],[StringLength],[Range]and[EmailAddress]. - DataAnnotations finds and runs the attributes with reflection when you validate. Here the checks are compiled into the validator.
- An attribute on the wrong kind of member is a build error.
[Range]on a member whose type has no ordering reportsVM1003. - A model that already uses DataAnnotations attributes can be compiled as it is.
[StringLength(50)]is a maximum here too. DataAnnotations names the minimumMinimumLength, and this library names itMin.
Packages
| Package | Use it for |
|---|---|
ValidationModules.Runtime |
Attributes, the validator interfaces, results, and service registration. Always required. |
ValidationModules.SourceGenerator |
The source generator and its analyzers. Always required. |
ValidationModules.AspNetCore |
Validating minimal API arguments and returning RFC 9457 problem details. |
ValidationModules.Options |
Validating options classes when the host starts. |
ValidationModules.Messages |
Error messages in German, Spanish, French, Japanese and Chinese. |
ValidationModules.SourceGenerator.Impl |
The generator's source, for building your own generator on top of it. |
Documentation
Contributing
AGENTS.md describes how to build and test the repository, and the conventions the code follows.
License
MIT. See LICENSE.txt.
| 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 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. |
-
net10.0
- ValidationModules.Runtime (>= 1.2.0)
-
net8.0
- ValidationModules.Runtime (>= 1.2.0)
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 |
|---|---|---|
| 1.2.0 | 0 | 9/25/2026 |
| 1.1.0 | 79 | 9/16/2026 |
| 1.0.0 | 98 | 8/31/2026 |
| 1.0.0-rc1015 | 95 | 8/31/2026 |
| 1.0.0-rc1014 | 120 | 8/30/2026 |
| 1.0.0-rc1013 | 102 | 8/30/2026 |
| 1.0.0-rc1012 | 92 | 8/29/2026 |
| 1.0.0-rc1011 | 102 | 8/29/2026 |
| 1.0.0-rc1010 | 97 | 8/29/2026 |
| 1.0.0-rc1009 | 102 | 8/28/2026 |
| 1.0.0-rc1008 | 102 | 8/28/2026 |
| 1.0.0-rc1007 | 123 | 8/27/2026 |
| 1.0.0-rc1006 | 109 | 8/16/2026 |
| 1.0.0-rc1005 | 107 | 8/16/2026 |
| 1.0.0-rc1004 | 103 | 8/16/2026 |