Nedo.AspNet.Common.Validation.Fluent 1.9.1

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

Nedo.AspNet.Common.Validation.Fluent

A fluent, type-safe API for defining validation rules on top of Nedo.AspNet.Common.Validation.Core. Inherit from AbstractValidator<T>, chain rules with RuleFor(), and get an IValidator<T> you can compose, inject, or test.

Install

dotnet add package Nedo.AspNet.Common.Validation.Fluent

Quick Start

using Nedo.AspNet.Common.Validation.Fluent;

public class UserValidator : AbstractValidator<UserInput>
{
    public UserValidator()
    {
        RuleFor(x => x.Name)
            .Required()
            .MinLength(3)
            .MaxLength(100)
            .Alpha();

        RuleFor(x => x.Email)
            .Required()
            .Matches(@"^[^@\s]+@[^@\s]+\.[^@\s]+$");

        RuleFor(x => x.Age)
            .Required()
            .GreaterThanOrEqual(18)
            .LessThanOrEqual(65);

        RuleFor(x => x.EmployeeCode)
            .Required()
            .NoWhitespace()
            .UpperCase()
            .StartsWith("EMP");
    }
}

// Usage
var validator = new UserValidator();
var result = validator.Validate(user, "id"); // Indonesian locale

if (!result.IsValid)
    foreach (var e in result.Errors)
        Console.WriteLine($"[{e.Code}] {e.Message}");

Architecture

AbstractValidator<T>  ──implements──▶  IValidator<T>
        │
        └── RuleFor(x => x.Prop)  →  RuleBuilder<T, TProp>
                │
                ├── .Required()          → RequiredValidator
                ├── .MinLength(n)        → MinLengthValidator
                ├── .Alpha()             → AlphaValidator
                ├── .GreaterThanOrEqual() → MinValueValidator
                └── .Must(custom)        → User-defined lambda

Each extension method internally delegates to the corresponding static validator from Nedo.AspNet.Common.Validation.Core. This means:

  • Same error codes — Fluent rules produce identical ValidationError codes as calling Core validators directly
  • Same localization — Culture-aware messages are resolved through the same .resx resources
  • Zero duplication — No separate validation logic; the Fluent layer is a thin wrapper

Available Extensions

General Extensions

Method Core Validator Error Code Description
.Required() RequiredValidator VAL-GEN-001 Not null, empty, or default
.MinLength(n) MinLengthValidator VAL-GEN-002 Minimum character length
.MaxLength(n) MaxLengthValidator VAL-GEN-003 Maximum character length
.ExactLength(n) ExactLengthValidator VAL-GEN-004 Exact character length
.Matches(regex) RegexValidator VAL-GEN-006 Regular expression match

String Extensions

Method Core Validator Error Code Description
.Alpha() AlphaValidator VAL-STR-007 Letters only (A–Z, a–z)
.AlphaNumeric() AlphaNumericValidator VAL-STR-010 Letters and digits only
.NoWhitespace() NoWhitespaceValidator VAL-STR-001 No spaces/tabs
.NoSpecialCharacter() NoSpecialCharacterValidator VAL-STR-008 No symbols or punctuation
.UpperCase() UpperCaseOnlyValidator VAL-STR-011 All uppercase
.LowerCase() LowerCaseOnlyValidator VAL-STR-012 All lowercase
.StartsWith(s) StartsWithValidator VAL-STR-003 Begins with prefix
.EndsWith(s) EndsWithValidator VAL-STR-004 Ends with suffix
.Contains(s) ContainsValidator VAL-STR-005 Contains substring
.NotContains(s) NotContainsValidator VAL-STR-006 Excludes substring

Numeric Extensions

For Nullable<T> properties where T : INumber<T> (int?, decimal?, double?, etc.):

Method Core Validator Error Code Description
.GreaterThanOrEqual(n) MinValueValidator VAL-NUM-001 Value ≥ n
.LessThanOrEqual(n) MaxValueValidator VAL-NUM-002 Value ≤ n
.Range(min, max) RangeValidator VAL-NUM-003 min ≤ value ≤ max
.Positive() PositiveNumberValidator VAL-NUM-005 Value > 0
.Negative() NegativeNumberValidator VAL-NUM-006 Value < 0
.NonZero() NonZeroValidator VAL-NUM-008 Value ≠ 0
.DivisibleBy(n) DivisibleByValidator VAL-NUM-011 Value % n == 0

Custom Rules

Use .Must() to add inline validation logic that isn't covered by built-in extensions:

Lambda with Error Details

RuleFor(x => x.Field).Must((value, fieldName, culture) =>
{
    if (value == null) return null; // let Required() handle nulls

    return value.StartsWith("VALID-")
        ? null
        : new ValidationError("CUSTOM-001", $"{fieldName} must start with VALID-", new[] { fieldName });
});

Simple Predicate

RuleFor(x => x.Code).Must(
    predicate: value => value.Length == 8,
    errorCode: "CUSTOM-002",
    errorMessage: "Code must be exactly 8 characters");

Localization

AbstractValidator<T>.Validate() accepts an optional culture parameter. This culture is passed down to every Core validator call, so messages are automatically resolved from the appropriate .resx file:

var validator = new UserValidator();

// English messages
var resultEn = validator.Validate(user, "en");

// Indonesian messages
var resultId = validator.Validate(user, "id");

// Default culture (English) when omitted
var resultDefault = validator.Validate(user);

Composing with Other Validators

AbstractValidator<T> implements IValidator<T>, so it works seamlessly with CompositeValidator<T> from the Core package:

using Nedo.AspNet.Common.Validation.Core;

// Combine Fluent + DSL + inline rules
var composite = new CompositeValidator<UserInput>()
    .Add(new UserValidator())            // Fluent validator
    .Add(dslCompiledValidator)           // DSL-compiled validator
    .Add((user, culture) =>              // Inline rule
        RequiredValidator.Validate(user.Name, "Name", culture ?? "en"));

var result = composite.Validate(user, "id");

Dependency Injection

Register your validators in the DI container and inject them where needed:

// Registration
services.AddSingleton<IValidator<UserInput>, UserValidator>();
services.AddSingleton<IValidator<OrderInput>, OrderValidator>();

// Usage in a controller or service
public class UserService
{
    private readonly IValidator<UserInput> _validator;

    public UserService(IValidator<UserInput> validator)
        => _validator = validator;

    public ValidationResult ValidateUser(UserInput input, string culture)
        => _validator.Validate(input, culture);
}

  • Nedo.AspNet.Common.Validation.Core — Core engine, 120+ static validators, CompositeValidator<T>
  • Nedo.AspNet.Common.Validation.Dsl — Text-based DSL for runtime rule definitions
Product Compatible and additional computed target framework versions.
.NET 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

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.9.1 47 2/13/2026
1.9.0 49 2/12/2026
1.8.0 46 2/12/2026