JAAvila.FluentOperations 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package JAAvila.FluentOperations --version 1.0.0
                    
NuGet\Install-Package JAAvila.FluentOperations -Version 1.0.0
                    
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="JAAvila.FluentOperations" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="JAAvila.FluentOperations" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="JAAvila.FluentOperations" />
                    
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 JAAvila.FluentOperations --version 1.0.0
                    
#r "nuget: JAAvila.FluentOperations, 1.0.0"
                    
#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 JAAvila.FluentOperations@1.0.0
                    
#: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=JAAvila.FluentOperations&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=JAAvila.FluentOperations&version=1.0.0
                    
Install as a Cake Tool

JAAvila.FluentOperations

Tests .NET C# License

A fluent validation and testing library for .NET that unifies inline assertions and model validation through Quality Blueprints with automatic scenario inference.

Packages

Package Description
JAAvila.FluentOperations Core library — inline .Test() assertions and Quality Blueprints
JAAvila.FluentOperations.DependencyInjection DI extensions for blueprint registration
JAAvila.FluentOperations.AspNetCore ASP.NET Core action filters for automatic validation
JAAvila.FluentOperations.MediatR MediatR pipeline behavior for request validation
dotnet add package JAAvila.FluentOperations

Quick Start

Inline Assertions

using JAAvila.FluentOperations;

// Strings
"user@example.com".Test().NotBeNull().NotBeEmpty().Contain("@").BeEmail();

// Numerics
42.Test().BePositive().BeLessThan(100).BeEven();
3.14m.Test().BeInRange(0m, 10m).HavePrecision(2);

// Date/Time
DateTime.Now.Test().BeToday().BeWeekday();

// Collections
new[] { 1, 2, 3 }.Test().HaveCount(3).Contain(2).BeInAscendingOrder();

// Exceptions
Action act = () => throw new InvalidOperationException("fail");
act.Test().Throw<InvalidOperationException>().WithMessage("*fail*");

// Assertion Scope (batch failures)
using (new AssertionScope())
{
    "".Test().NotBeEmpty();
    0.Test().BePositive();
}
// Throws single exception with all failures combined

Quality Blueprints (Model Validation)

public class UserBlueprint : QualityBlueprint<User>
{
    public UserBlueprint()
    {
        using (Define())
        {
            For(x => x.Email).Test().NotBeNull().NotBeEmpty().BeEmail();
            For(x => x.Name).Test().NotBeNull().HaveMinLength(2);
            For(x => x.Age).Test().BeInRange(18, 120);
        }
    }
}

var blueprint = new UserBlueprint();
var report = blueprint.Check(new User { Email = "", Name = "J", Age = 15 });

if (!report.IsValid)
{
    foreach (var failure in report.Failures)
        Console.WriteLine($"{failure.PropertyName}: {failure.Message}");
}

Supported Types

Category Types Operations
String string? 45+ ops: Be, NotBe, BeEmpty, Contain, Match (regex), BeEmail, BeUrl, BeJson, BeXml, BeSemVer, BeIPAddress, BeCreditCard, MatchWildcard, ContainAll, ContainAny...
Boolean bool, bool? Be, BeTrue, BeFalse, BeAllTrue, BeAllFalse, Imply, HaveValue
Numeric int, long, decimal, double, float (+ nullable) Be, BePositive, BeNegative, BeZero, BeGreaterThan, BeLessThan, BeInRange, BeOneOf, BeDivisibleBy, BeEven, BeOdd, BeApproximately, HavePrecision, BeNaN, BeInfinity, BeFinite...
Date/Time DateTime, DateOnly, TimeOnly, TimeSpan, DateTimeOffset (+ nullable) Be, BeAfter, BeBefore, BeInRange, BeToday, BeInThePast, BeInTheFuture, BeWeekday, BeCloseTo, HaveYear...
Collections IEnumerable<T>, T[], Dictionary<TKey,TValue> HaveCount, Contain, ContainAll, ContainInOrder, BeSubsetOf, BeInAscendingOrder, AllSatisfy, BeUnique, HaveElementAt, SatisfyRespectively, HaveMinCount...
Special Guid, Guid?, Enum<T>, Uri? Be, BeEmpty, BeDefined, HaveFlag, HaveScheme, BeAbsolute...
Object object? BeNull, NotBeNull, BeSameAs, BeOfType, BeEquivalentTo
Action Action, Func<Task> Throw, ThrowExactly, NotThrow, NotThrowAfter, CompleteWithinAsync

Blueprint Features

Scenario-Based Validation

// Define your own marker interfaces — Scenario<T> works with any interface
public interface ICreateOrder { }
public interface IUpdateOrder { }

public class OrderBlueprint : QualityBlueprint<Order>
{
    public OrderBlueprint()
    {
        using (Define())
        {
            For(x => x.OrderId).Test().NotBeNull(); // Always applied

            Scenario<ICreateOrder>(() =>
            {
                For(x => x.CustomerId).Test().NotBeNull();
            });

            Scenario<IUpdateOrder>(() =>
            {
                For(x => x.Status).Test().NotBe("Closed");
            });
        }
    }
}

// Automatic scenario inference from interfaces
public class OrderForCreate : Order, ICreateOrder { }
var report = blueprint.Check(new OrderForCreate { ... }); // global + create rules

Severity, Error Codes, Custom Messages

using (Define())
{
    For(x => x.Email, new RuleConfig
    {
        Severity = Severity.Error,
        ErrorCode = "EMAIL_REQUIRED",
        CustomMessage = "A valid email is required"
    }).Test().NotBeNull().BeEmail();

    For(x => x.Nickname, new RuleConfig { Severity = Severity.Warning })
        .Test().HaveMinLength(3);
}

var report = blueprint.Check(model);
report.HasErrors;    // Only Severity.Error
report.HasWarnings;  // Only Severity.Warning
report.Errors;       // Filtered list

Async Validation

using (Define())
{
    ForAsync(x => x.Email, async email =>
    {
        return await emailService.IsAvailableAsync(email);
    }, "Email is already taken");
}

var report = await blueprint.CheckAsync(model);

Cross-Property Comparison

using (Define())
{
    ForCompare(x => x.StartDate, x => x.EndDate).BeLessThan();
    ForCompare(x => x.Password, x => x.ConfirmPassword).Be();
}

Conditional Validation

using (Define())
{
    When(
        condition: x => x.IsInternational,
        then: () =>
        {
            For(x => x.PassportNumber).Test().NotBeNull();
        },
        otherwise: () =>
        {
            For(x => x.NationalId).Test().NotBeNull();
        }
    );
}

Nested Objects, ForEach, Include

using (Define())
{
    // Nested object validation
    ForNested(x => x.Address, new AddressBlueprint());

    // Per-item collection validation
    ForEach(x => x.Items, new OrderItemBlueprint());

    // Compose blueprints
    Include(new BaseEntityBlueprint());
}

CascadeMode

public class StrictBlueprint : QualityBlueprint<Order>
{
    public StrictBlueprint()
    {
        CascadeMode = CascadeMode.StopOnFirstFailure;

        using (Define())
        {
            For(x => x.Email).Test().NotBeNull().BeEmail();
        }
    }
}

Transformation Rules

using (Define())
{
    // Validate a transformed value (same-type: trim whitespace)
    ForTransform(x => x.Email, email => email?.Trim())
        .Test().NotBeNull().NotBeEmpty();

    // Cross-type: transform DateTime → int, then validate as integer
    ForTransform(x => x.BirthDate, (DateTime d) => DateTime.Now.Year - d.Year)
        .Test().BeGreaterThanOrEqualTo(18);
}

Custom Validators

public class LuhnValidator : ICustomValidator<string?>
{
    public bool Validate(string? value) => /* Luhn algorithm */;
    public string FailureMessage => "Invalid card number";
}

using (Define())
{
    ForCustom(x => x.CardNumber, new LuhnValidator());
}

Framework Integration

ASP.NET Core

dotnet add package JAAvila.FluentOperations.AspNetCore
builder.Services.AddControllers(options =>
{
    options.AddBlueprintValidation();
});
builder.Services.AddBlueprintValidationFilter();
builder.Services.AddSingleton<OrderBlueprint>();

MediatR

dotnet add package JAAvila.FluentOperations.MediatR
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(assembly));
builder.Services.AddBlueprintValidation();
builder.Services.AddSingleton<CreateOrderCommandBlueprint>();

See Integration Guide for full examples.

Documentation

Project Stats

  • 2906 tests across NUnit and xUnit projects
  • 415+ validators covering 20+ data types
  • 34 operation managers with fluent chaining
  • 4 NuGet packages (core + 3 integrations)
  • CI/CD via GitHub Actions (build + test matrix, NuGet release on tags)
  • Performance optimized with lazy initialization, caching, and zero-allocation patterns

License

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

Author

Built by JAAvila

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 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 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 (8)

Showing the top 5 NuGet packages that depend on JAAvila.FluentOperations:

Package Downloads
JAAvila.FluentOperations.MediatR

MediatR integration for JAAvila.FluentOperations Quality Blueprints. Provides pipeline behaviors for automatic request validation.

JAAvila.FluentOperations.DependencyInjection

Dependency Injection extensions for JAAvila.FluentOperations Quality Blueprints.

JAAvila.FluentOperations.AspNetCore

ASP.NET Core integration for JAAvila.FluentOperations Quality Blueprints. Provides action filters for automatic model validation.

JAAvila.FluentOperations.MinimalApi

Minimal API integration for JAAvila.FluentOperations Quality Blueprints. Provides endpoint filters for automatic model validation with RFC 7807 Problem Details.

JAAvila.FluentOperations.Grpc

gRPC server interceptor integration for JAAvila.FluentOperations Quality Blueprints. Provides automatic request validation with structured error metadata in gRPC trailers.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.5.2 96 4/3/2026
1.5.1 99 3/29/2026
1.5.0 215 3/29/2026
1.3.0 201 3/26/2026
1.2.0 84 3/21/2026
1.1.0 208 3/21/2026
1.0.3-alpha.0.2 40 3/18/2026
1.0.3-alpha.0.1 40 3/18/2026
1.0.2 92 3/17/2026
1.0.2-alpha.0.4 49 3/14/2026
1.0.2-alpha.0.3 110 3/14/2026
1.0.2-alpha.0.2 46 3/14/2026
1.0.2-alpha.0.1 45 3/14/2026
1.0.1 136 3/9/2026
1.0.0 137 3/8/2026