Vali-Validation 2.0.2

dotnet add package Vali-Validation --version 2.0.2
                    
NuGet\Install-Package Vali-Validation -Version 2.0.2
                    
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="Vali-Validation" Version="2.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Vali-Validation" Version="2.0.2" />
                    
Directory.Packages.props
<PackageReference Include="Vali-Validation" />
                    
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 Vali-Validation --version 2.0.2
                    
#r "nuget: Vali-Validation, 2.0.2"
                    
#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 Vali-Validation@2.0.2
                    
#: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=Vali-Validation&version=2.0.2
                    
Install as a Cake Addin
#tool nuget:?package=Vali-Validation&version=2.0.2
                    
Install as a Cake Tool

Vali-Validation

Vali-Validation is a lightweight, zero-dependency fluent validation library for .NET 7, 8, and 9. It provides a clean, expressive API for defining validation rules on your models, with full support for async validation, conditional rules, nested object validation, collection validation, cascade mode, error codes, custom rules, and seamless dependency injection — all without requiring any external dependencies beyond Microsoft.Extensions.DependencyInjection.Abstractions.

Installation

dotnet add package Vali-Validation

Quick Start

Define a validator by subclassing AbstractValidator<T> and configuring rules in the constructor:

using Vali_Validation.Core.Validators;

public class CreateUserDto
{
    public string? Name { get; set; }
    public string? Email { get; set; }
    public string? Password { get; set; }
    public int Age { get; set; }
}

public class CreateUserValidator : AbstractValidator<CreateUserDto>
{
    public CreateUserValidator()
    {
        RuleFor(x => x.Name)
            .NotEmpty()
            .MinimumLength(2)
            .MaximumLength(100);

        RuleFor(x => x.Email)
            .NotEmpty()
            .Email();

        RuleFor(x => x.Password)
            .NotEmpty()
            .MinimumLength(8)
            .HasUppercase()
            .HasLowercase()
            .HasDigit()
            .HasSpecialChar();

        RuleFor(x => x.Age)
            .GreaterThanOrEqualTo(18)
            .LessThan(120);
    }
}

Use the validator:

var validator = new CreateUserValidator();
var result = validator.Validate(dto);

if (!result.IsValid)
{
    foreach (var error in result.ToFlatList())
        Console.WriteLine(error);
}

// Async
var result = await validator.ValidateAsync(dto, cancellationToken);

// Throw on failure
validator.ValidateAndThrow(dto);
await validator.ValidateAndThrowAsync(dto, cancellationToken);

Available Rules

Rule Description
NotEmpty() Value must not be null or whitespace
NotNull() Value must not be null
Null() Value must be null
Empty() Value must be null or empty string
Must(predicate) Custom sync predicate
MustAsync(predicate) Custom async predicate
MustAsync(predicate, ct) Custom async predicate with CancellationToken
Custom(action) Custom validation action with full context
MinimumLength(n) String length >= n
MaximumLength(n) String length ⇐ n
LengthBetween(min, max) String length between min and max
Matches(pattern) Must match regex pattern
Email() Must be a valid email address
Url() Must be a valid HTTP/HTTPS URL
PhoneNumber() Must be a valid E.164 phone number
IPv4() Must be a valid IPv4 address
CreditCard() Must pass Luhn check
Guid() Must be a valid GUID string
NotEmptyGuid() Must be a non-empty GUID
IsAlpha() Only alphabetic characters
IsAlphanumeric() Only alphanumeric characters
IsNumeric() Only numeric characters
NoWhitespace() No whitespace characters
EqualTo(value) Must equal the given value
NotEqual(value) Must not equal the given value
EqualToProperty(expr) Must equal another property
GreaterThan(n) Must be greater than n
LessThan(n) Must be less than n
GreaterThanOrEqualTo(n) Must be >= n
LessThanOrEqualTo(n) Must be ⇐ n
Between(min, max) Inclusive range
ExclusiveBetween(min, max) Exclusive range
Positive() Must be > 0
Negative() Must be < 0
NotZero() Must not be 0
Odd() Must be an odd integer
Even() Must be an even integer
MultipleOf(factor) Must be a multiple of factor
MaxDecimalPlaces(n) At most n decimal places
In(values) Must be in the allowed list
NotIn(values) Must not be in the disallowed list
StartsWith(prefix) String must start with prefix
EndsWith(suffix) String must end with suffix
MustContain(substring) String must contain substring
NotContains(substring) String must not contain substring
FutureDate() DateTime must be in the future
PastDate() DateTime must be in the past
Today() DateTime must be today
IsEnum<TEnum>() Must be a valid enum value
HasCount(n) Collection must have exactly n items
MinCount(n) Collection must have at least n items
MaxCount(n) Collection must have at most n items
NotEmptyCollection() Collection must not be empty
Unique() Collection must have no duplicates
AllSatisfy(predicate) All collection items must satisfy predicate
AnySatisfy(predicate) At least one item must satisfy predicate
HasUppercase() String must contain an uppercase letter
HasLowercase() String must contain a lowercase letter
HasDigit() String must contain a digit
HasSpecialChar() String must contain a special character
Lowercase() String must be all lowercase
Uppercase() String must be all uppercase
MinWords(n) String must have at least n words
MaxWords(n) String must have at most n words

Modifiers

Modifier Description
WithMessage(msg) Override the error message; supports {PropertyName} and {PropertyValue}
WithErrorCode(code) Attach an error code to the rule
OverridePropertyName(name) Use a custom key in error dictionaries
StopOnFirstFailure() Stop evaluating rules for this property after first failure
When(condition) Only run preceding rules when condition is true
Unless(condition) Only run preceding rules when condition is false
WhenAsync(condition) Async version of When
UnlessAsync(condition) Async version of Unless

Message Templates

Error messages support {PropertyName} and {PropertyValue} placeholders:

RuleFor(x => x.Age)
    .GreaterThan(0)
    .WithMessage("'{PropertyName}' value '{PropertyValue}' must be positive.");

CascadeMode

Stop validation after the first property failure across all properties:

public class MyValidator : AbstractValidator<MyDto>
{
    protected override CascadeMode GlobalCascadeMode => CascadeMode.StopOnFirstFailure;

    public MyValidator()
    {
        RuleFor(x => x.Name).NotEmpty();
        RuleFor(x => x.Email).Email(); // Skipped if Name already fails
    }
}

Nested Validators

RuleFor(x => x.Address).SetValidator(new AddressValidator());

Collection Validation

RuleForEach(x => x.Tags).NotEmpty().MinimumLength(2);

DI Registration

// Register all validators from an assembly
services.AddValidationsFromAssembly(typeof(CreateUserValidator).Assembly);

// Or register individually
services.AddScoped<IValidator<CreateUserDto>, CreateUserValidator>();

Donations

If Vali-Validation is useful to you, consider supporting its development:


License

Apache License 2.0

Contributions

Issues and pull requests are welcome on GitHub.

Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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 was computed.  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 (3)

Showing the top 3 NuGet packages that depend on Vali-Validation:

Package Downloads
Vali-Validation.MediatR

MediatR integration for Vali-Validation. Adds a ValidationBehavior<TRequest, TResponse> pipeline behavior that automatically validates IRequest objects using Vali-Validation before they reach their handler. Throws ValidationException on failure. Use Vali-Mediator.Validation instead if you use Vali-Mediator — it provides richer integration with Result<T> support (no exceptions needed).

Vali-Validation.ValiMediator

Vali-Mediator integration for Vali-Validation. Adds a ValidationBehavior<TRequest, TResponse> that validates IRequest objects before they reach their handler. When TResponse is Result<T>, validation failures are returned as Result.Fail(errors, ErrorType.Validation) — no exceptions needed. For other response types, throws ValidationException. Package name: Vali-Validation.ValiMediator. Requires Vali-Mediator.

Vali-Validation.AspNetCore

ASP.NET Core integration for Vali-Validation. Provides: - ValiValidationMiddleware: catches ValidationException and returns HTTP 400 problem+json. - ValiValidationFilter<T>: Minimal API endpoint filter for automatic request validation. - ValiValidateAttribute: MVC action filter for automatic controller action validation. - UseValiValidationExceptionHandler() and WithValiValidation<T>() extension methods.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.2 176 4/14/2026
2.0.1 244 3/18/2026
2.0.0 187 3/16/2026
1.0.0 284 4/16/2025

v2.0.2 — Bug fix for async validation messages:
           - Fixed MustAsync() to properly support .WithMessage() for custom error messages on async rules.
           - Created MessageWrapper to allow message updates after async rule registration.
           - Async validation messages now correctly override default messages.

           v2.0.0 — Major improvements and new features:

           Bug fixes:
           - ValidateAsync now exposed on IValidator<T> interface (was missing).
           - Validate() no longer deadlocks in ASP.NET Core: sync and async rules run in separate lists.
           - LessThan() had wrong error message ("greater than") — fixed.
           - Positive() no longer accepts zero (semantics fix).
           - Expression body crash fixed for non-MemberExpression selectors (e.g. x => x.Name.ToLower()).
           - MustAsync no longer registers an empty sync delegate unnecessarily.
           - isValidAlpha renamed to IsValidAlpha (naming convention fix).

           Design improvements:
           - ValidationResult.Errors changed from Dictionary<string, List<string?>> to List<string> (errors are never null).
           - Constants.cs removed (Zero/One literals added no value).
           - AddValidationsFromAssembly now accepts optional ServiceLifetime parameter (default Transient).
           - New ValidationException typed exception in Core/Exceptions/.
           - ValidateAndThrow() and ValidateAndThrowAsync() added to AbstractValidator.

           New features:
           - When(Func<T, bool>) / Unless(Func<T, bool>) — conditional rule execution.
           - StopOnFirstFailure() — stop evaluating rules for a property after first failure.
           - SetValidator(AbstractValidator<TProperty>) — delegate validation to nested validators.
           - RuleForEach(x => x.Collection) — validate each element with indexed error keys (Items[0]).
           - OverridePropertyName(string) — control the error key in ValidationResult.Errors.