ExpressValidator.Extensions.ValidationOnStart 0.2.0

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

A lightweight library that brings expressive, fail-fast validation to .NET configuration options using the power of FluentValidation via the ExpressValidator library.

✨ Key Features

  • Fail-fast validation on startup with the AddOptionsWithExpressValidation<MyOptions> method
  • Validation failures are converted to a standard ValidateOptionsResult with detailed messages
  • Detailed error reporting - OptionsValidationException or AggregateException can be handled at startup
  • Configurable validation: stop on the first error or continue validating an option using ExpressValidator.OnFirstPropertyValidatorFailed.
  • Zero boilerplate - no need to create separate AbstractValidator classes
  • Fluent API - for property-level rules
  • Uses IValidateOptions<TOptions> under the hood

⚡ Quick Start

// 1. Define Your Options Classes
public class MyOptions1
{
	public int Option1 { get; set; }
	public int Option2 { get; set; }
}

public class MyOptions2
{
	public int Option3 { get; set; }
	public int Option4 { get; set; }
}

// 2. Configure Validation in Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Services
	.AddOptionsWithExpressValidation<MyOptions1>(
	(eb) =>
			// Select the options property to validate
			eb.AddProperty(o => o.Option1)
			// Define FluentValidation rules
			.WithValidation(o => o.GreaterThan(10))
			.AddProperty(o => o.Option2)
			.WithValidation(o => o.GreaterThan(20))
	// Configuration section name
	, "MyOptions1"
	// Fail fast when validation fails (optional; default behavior is to collect all errors)
	, ExpressValidator.OnFirstPropertyValidatorFailed.Break)

	.AddOptionsWithExpressValidation<MyOptions2>(
	(eb) =>
			eb.AddProperty(o => o.Option3)
			.WithValidation(o => o.GreaterThan(30))
			.AddProperty(o => o.Option4)
			.WithValidation(o => o.GreaterThan(40))
	, "MyOptions2");

var loggerFactory = LoggerFactory.Create(lb => lb.AddConsole());
var logger = loggerFactory.CreateLogger<Program>();

 // 3. Handle Validation Errors
try
{
	var app = builder.Build();
	// This endpoint returns a message when all options are valid.
	app.MapGet("/",
		(IOptions<MyOptions1> options1, IOptions<MyOptions2> options2) => "The option values " +
			$"{options1.Value.Option1}, " +
			$"{options1.Value.Option2}, " +
			$"{options2.Value.Option3}, " +
			$"and {options2.Value.Option4} are correct!");

	await app.RunAsync();
}
// Single options type validation failure.
catch (OptionsValidationException ove)
{
	foreach (var failure in ove.Failures)
	{
		logger.LogCritical(
			"Options validation failure: {Failure}",
			failure
		);
	}

	logger.LogCritical(ove, "Options validation exception thrown");
}
// Multiple options types validation failures (e.g., both MyOptions1 and MyOptions2)
catch (AggregateException ae) when (ae.InnerExceptions.All(e => e is OptionsValidationException))
{
	foreach (var failure in ae
			.Flatten()
			.InnerExceptions
			.Cast<OptionsValidationException>()
			.SelectMany(ex => ex.Failures))
	{
		logger.LogCritical(
			"Options validation failure: {Failure}",
			failure
		);
	}

	logger.LogCritical(ae, "AggregateException thrown");
}
catch (Exception ex)
{
	logger.LogCritical(ex, "An unhandled exception occurred during application startup.");
}

In the appsettings.json

{
...
"MyOptions1": {
  "Option1": 9,
  "Option2": 19
},
"MyOptions2": {
  "Option3": 29,
  "Option4": 39
}
...
}

🧩 How It Works

AddOptionsWithExpressValidation<TOptions>

  • Registers options
  • Attaches express validation, and enables ValidateOnStart
  • Binds configuration values using the provided section name

ExpressOptionsValidator<TOptions>

  • Implements IValidateOptions<TOptions>
  • Runs the express validator against your options.
  • Converts validation results into ValidateOptionsResult
  • Produces per-property error messages

🏆 Sample

See samples folder for concrete example.

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

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
0.2.0 0 12/23/2025
0.2.0-preview 218 12/18/2025
0.1.0-preview 186 12/15/2025