SebastianGuzmanMorla.Validator 1.0.3

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

SebastianGuzmanMorla.Validator

A strongly-typed validation library for .NET that allows you to easily build entity validators with support for custom validation rules, conditional logic, nested entity mapping, and automated dependency injection registration using a Roslyn Source Generator.

Features

  • Strongly-typed validation: Write distinct validators specific to each entity model.
  • Fluent Property Rules: Chain validation rules on individual properties cleanly.
  • Conditional Validation: Run validation rules only when dynamic conditions are satisfied.
  • Interface Cascading: Automatically execute and weave validation rules across implemented interfaces.
  • Source Generator: Automates validator registration in Microsoft.Extensions.DependencyInjection.
  • Flexible Control Flow: Configure rule chains to continue or stop validation upon failure.

Installation

Install the NuGet package:

dotnet add package SebastianGuzmanMorla.Validator

Basic Usage

1. Create a model

First, define the entity model you want to validate:

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

2. Implement the Validator

Create a validator class inheriting from Validator<TEntity> and define rules inside the constructor:

using SebastianGuzmanMorla.Validator;

public class UserValidator : Validator<User>
{
    public UserValidator()
    {
        RuleFor(u => u.Name)
            .NotNull((_, _) => "Name cannot be null")
            .NotEmpty((_, _) => "Name is required");

        RuleFor(u => u.Email)
            .NotNull((_, _) => "Email cannot be null")
            .NotEmpty((_, _) => "Email is required")
            .EmailAddress((_, _) => "Email must be a valid address");

        RuleFor(u => u.Age)
            .NotNull((_, _) => "Age cannot be null")
            .Minimum(1, (_, _) => "Age must be greater than 0");
    }
}

3. Service Configuration (Dependency Injection)

The Roslyn Source Generator automatically generates the registration logic inside a partial ConfigureServices class:

public partial class ConfigureServices
{
    private static partial void RegisterValidators(IServiceCollection services);

    public static IServiceCollection ConfigureDomain(this IServiceCollection services)
    {
        // Automatically registers all validators in the assembly as Singletons
        RegisterValidators(services);

        return services;
    }
}

4. Execute the Validator

Inject IValidator<T> into your services or Minimal API endpoints to run validations:

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

builder.Services.ConfigureDomain();

WebApplication app = builder.Build();

app.MapPost("/users", async (User user, [FromServices] IServiceProvider serviceProvider, [FromServices] IValidator<User> validator) =>
{
    var result = await validator.Validate(user, serviceProvider);
    
    if (!result.IsValid)
    {
        return Results.BadRequest(new 
        { 
            Errors = result.Errors 
        });
    }
    
    return Results.Created($"/users/{user.Id}", user);
});

app.Run();

Advanced Examples

Interface Validation Cascading

You can validate shared attributes by defining rules on interfaces. The Source Generator automatically weaves these rules into any concrete classes that implement the interface.

Define your validation interface inheriting from IEntityValidation:

public interface IDeviceIdValidation : IEntityValidation
{
    public Guid DeviceId { get; set; }
}

Create a validator for the interface:

public class DeviceIdValidator : Validator<IDeviceIdValidation>
{
    public DeviceIdValidator()
    {
        RuleFor(x => x.DeviceId)
            .NotEmpty((_, _) => "Device ID cannot be empty");
    }
}

Implement the interface on a concrete entity class (declared as partial) and define the class validator:

public class Device : IDeviceIdValidation
{
    public Guid DeviceId { get; set; }
    public string? Name { get; set; }
}

public partial class DeviceValidator : Validator<Device>
{
    public DeviceValidator()
    {
        RuleFor(d => d.Name)
            .NotEmpty((_, _) => "Device name is required");
    }
}

The Source Generator will automatically weave the validations behind the scenes:

// Automatically generated by the Source Generator:
public partial class DeviceValidator
{
    protected override ImmutableArray<Func<IServiceProvider, Device, CancellationToken, Task<ValidationResult>>> InterfaceValidations =>
    [
        (serviceProvider, entity, cancellationToken) => 
            serviceProvider.GetRequiredService<IValidator<IDeviceIdValidation>>().Validate(entity, serviceProvider, cancellationToken)
    ];
}

Conditional Validation (RuleForWhen)

To conditionally run rules based on a dynamic runtime check, use RuleForWhen instead of RuleFor:

public class UserValidator : Validator<User>
{
    public UserValidator()
    {
        RuleForWhen(u => u.PromoCode, (serviceProvider, user, cancellationToken) => 
            Task.FromResult(user.HasOptedInForPromo)
        )
        .NotEmpty((_, _) => "Promo code is required when promotional offers are enabled");
    }
}

Nested Entities and Collections (ValidateEntity)

Validate nested objects or collections of entities recursively. The library will resolve the appropriate validators from DI and append deep paths to error keys (e.g., Headquarters.Street or Employees[0].Name):

public class Company
{
    public Address Headquarters { get; set; }
    public List<Employee> Employees { get; set; }
}

public class CompanyValidator : Validator<Company>
{
    public CompanyValidator()
    {
        // Validates Headquarters using IValidator<Address>
        ValidateEntity(c => c.Headquarters);

        // Validates each item in the collection using IValidator<Employee>
        ValidateEntity(c => c.Employees);
    }
}

API Reference

Validator Methods

  • RuleFor(propertyExpression): Sets up validation rules on a property.
  • RuleForWhen(propertyExpression, asyncPredicate): Sets up conditional validation rules.
  • ValidateEntity(propertyExpression): Configures nested entity or collection validation.

Validation Rules (ValidationPropertyRules)

All rules accept an optional ValidationErrorHandle parameter at the end of the method chain to control execution flow (Continue, StopProperty, or StopAll).

  • NotNull(messageFunc): Asserts property is not null.
  • NotEmpty(messageFunc): Asserts string is not empty/whitespace, collection has elements, or Guid is not Guid.Empty.
  • EmailAddress(messageFunc): Validates email format.
  • Equal(value, messageFunc): Asserts property value equals a constant.
  • Equal(propertyExpression, messageFunc): Asserts property value equals another property on the same entity.
  • NotEqual(value, messageFunc): Asserts property value does not equal a constant.
  • NotEqual(propertyExpression, messageFunc): Asserts property value does not equal another property.
  • Minimum(value, messageFunc): Asserts value is >= value.
  • Maximum(value, messageFunc): Asserts value is <= value.
  • MinimumLength(length, messageFunc): Asserts string length is >= length.
  • MaximumLength(length, messageFunc): Asserts string length is <= length.
  • Between(min, max, messageFunc): Asserts value is in inclusive range [min, max].
  • Matches(regex, messageFunc): Asserts string matches regex pattern.
  • Must(predicate, messageFunc): Asynchronous predicate returning Task<bool> with a predefined message.
  • Must(dynamicPredicate): Asynchronous predicate returning Task<(bool IsValid, string? ErrorMessage)> with dynamic error details returned from execution.

Validation Result

ValidationResult exposes:

  • IsValid: Boolean indicating validation success.
  • Errors: Dictionary where key is the property path and value is a list of error strings.

Requirements

  • .NET 10.0 or higher
  • Microsoft.Extensions.DependencyInjection

License

This project is licensed under the MIT License - see the LICENSE file for details.

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 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. 
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 SebastianGuzmanMorla.Validator:

Package Downloads
SebastianGuzmanMorla.DDD.Domain

Biblioteca de dominio que define entidades base, mensajes y atributos para la implementación de Domain-Driven Design (DDD) en .NET 10.0+.

SebastianGuzmanMorla.DDD

Biblioteca base para la implementación de Domain-Driven Design (DDD) en .NET 10.0+ con soporte para repositorios EF Core, Unit of Work y Source Generators.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.3 117 7/21/2026
1.0.2 976 5/26/2026
1.0.1 125 4/17/2026
1.0.0 129 4/17/2026 1.0.0 is deprecated because it has critical bugs.