ResultR.Validation 1.0.1

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

ResultR.Validation

GitHub Actions Workflow Status NuGet Version NuGet Downloads GitHub License

📖 Overview

Lightweight inline validation framework for ResultR. Define validation rules directly in your ValidateAsync() method using a fluent API, with seamless integration into ResultR's pipeline hooks.

What it does:

  • Validates requests using a fluent API
  • Integrates seamlessly with ResultR's pipeline hooks
  • Returns Result.Success() or Result.Failure() with aggregated errors

📋 Requirements

  • .NET 10.0 or later
  • C# 14.0 or later

📥 Installation

dotnet add package ResultR.Validation

🚀 Quick Start

using ResultR;
using ResultR.Validation;

public record CreateUserRequest(string Email, string Name, int Age) : IRequest<User>;

public class CreateUserHandler : IRequestHandler<CreateUserRequest, User>
{
    public ValueTask<Result> ValidateAsync(CreateUserRequest request)
    {
        return Validator.For(request)
            .RuleFor(x => x.Email)
                .NotEmpty("Email is required")
                .EmailAddress("Invalid email format")
            .RuleFor(x => x.Name)
                .NotEmpty("Name is required")
                .MinLength(2, "Name must be at least 2 characters")
                .MaxLength(100, "Name cannot exceed 100 characters")
            .RuleFor(x => x.Age)
                .GreaterThan(0, "Age must be positive")
                .LessThanOrEqualTo(150, "Age must be realistic")
            .ToResult();
    }

    public async ValueTask<Result<User>> HandleAsync(CreateUserRequest request, CancellationToken ct)
    {
        var user = new User(request.Email, request.Name, request.Age);
        // Save user...
        return Result<User>.Success(user);
    }
}

Features

  • Zero ceremony - No external validator classes, no DI registration for validators
  • Inline validation - Define rules directly in ValidateAsync() using a fluent API
  • Seamless integration - Works with ResultR's IRequestHandler<TRequest> and IRequestHandler<TRequest, TResponse>
  • Automatic result conversion - Returns Result.Success() or Result.Failure() with aggregated errors
  • Comprehensive built-in rules - String, numeric, collection, and custom validations

Built-in Validation Rules

String Validations

  • NotEmpty() - Ensures string is not null, empty, or whitespace
  • NotNull() - Ensures value is not null
  • MinLength(int) - Minimum string length
  • MaxLength(int) - Maximum string length
  • Length(int, int) - String length range
  • Matches(string pattern) - Regex pattern matching
  • EmailAddress() - Valid email format

Numeric Validations

  • GreaterThan(T) - Value must be greater than comparison
  • GreaterThanOrEqualTo(T) - Value must be greater than or equal to comparison
  • LessThan(T) - Value must be less than comparison
  • LessThanOrEqualTo(T) - Value must be less than or equal to comparison
  • Between(T, T) - Value must be within range (inclusive)

Collection Validations

  • NotEmpty() - Collection must contain at least one element

General Validations

  • NotNull() - Value must not be null
  • Equal(T) - Value must equal comparison
  • NotEqual(T) - Value must not equal comparison
  • Must(Func<T, bool>) - Custom predicate validation

Custom Validation Rules

Use the Must() method for custom validation logic:

public ValueTask<Result> ValidateAsync(CreateUserRequest request)
{
    return Validator.For(request)
        .RuleFor(x => x.Email)
            .NotEmpty("Email is required")
            .Must(email => email.EndsWith("@company.com"), "Must use company email")
        .RuleFor(x => x.Name)
            .Must(name => !name.Contains("admin", StringComparison.OrdinalIgnoreCase), 
                  "Name cannot contain 'admin'")
        .ToResult();
}

Accessing Validation Errors

When validation fails, errors are stored in the Result metadata:

var result = await mediator.SendAsync(request);

if (result.IsFailure)
{
    var errors = result.GetMetadataValueOrDefault<List<ValidationError>>(ValidationMetadataKeys.ValidationErrors);
    
    if (errors is not null)
    {
        foreach (var error in errors)
        {
            Console.WriteLine($"{error.PropertyName}: {error.ErrorMessage}");
        }
    }
}

// Example output:
// Email: Email is required
// Name: Name must be at least 2 characters
// Age: Age must be positive

How It Works

  1. Validator.For(request) creates a ValidationBuilder<T> for the request
  2. Each RuleFor() call selects a property and returns a RuleBuilder<T, TProperty>
  3. Validation methods (e.g., NotEmpty(), MinLength()) add rules to an internal list
  4. ToResult() executes all rules and returns:
    • Result.Success() if all rules pass
    • Result.Failure("Validation failed") with errors in metadata if any rule fails

❓ Why ResultR.Validation?

Unlike FluentValidation which requires separate validator classes and DI registration, ResultR.Validation lets you define validation rules inline within your handler's ValidateAsync() method. This reduces ceremony and keeps validation logic close to your business logic.

💬 Support

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

ISC License - see the LICENSE file for details.


Built with ❤️ for the C# / DotNet community.

Product Compatible and additional computed target framework versions.
.NET 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

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.0.1 85 1/2/2026
1.0.0 86 12/28/2025