TimeWarp.OptionsValidation
                             
                            
                                1.0.0-beta.3
                            
                        
                            
                                
                                
                                    Prefix Reserved
                                
                            
                    dotnet add package TimeWarp.OptionsValidation --version 1.0.0-beta.3
NuGet\Install-Package TimeWarp.OptionsValidation -Version 1.0.0-beta.3
<PackageReference Include="TimeWarp.OptionsValidation" Version="1.0.0-beta.3" />
<PackageVersion Include="TimeWarp.OptionsValidation" Version="1.0.0-beta.3" />
<PackageReference Include="TimeWarp.OptionsValidation" />
paket add TimeWarp.OptionsValidation --version 1.0.0-beta.3
#r "nuget: TimeWarp.OptionsValidation, 1.0.0-beta.3"
#:package TimeWarp.OptionsValidation@1.0.0-beta.3
#addin nuget:?package=TimeWarp.OptionsValidation&version=1.0.0-beta.3&prerelease
#tool nuget:?package=TimeWarp.OptionsValidation&version=1.0.0-beta.3&prerelease
TimeWarp.OptionsValidation
TimeWarp.OptionsValidation integrates FluentValidation with Microsoft.Extensions.Options to provide automatic validation of your configuration settings at application startup.
Why Use This Library?
Configuration errors are a common source of runtime failures. TimeWarp.OptionsValidation helps you fail fast by validating all configuration settings when your application starts, rather than discovering errors when the configuration is first accessed (which could be hours or days later in production).
Key Benefits:
- Validates configuration settings using FluentValidation rules
- Integrates seamlessly with Microsoft.Extensions.Options
- Catches configuration errors at startup, not at runtime
- Provides clear, actionable error messages
- Supports both IConfiguration binding and programmatic configuration
Give a Star! ⭐
If you like or are using this project please give it a star. Thank you!
Installation
dotnet add package TimeWarp.OptionsValidation
You can see the latest NuGet packages from the official TimeWarp NuGet page.
Usage
Basic Setup with Automatic Startup Validation
Use AddFluentValidatedOptions() which returns OptionsBuilder<T>, allowing you to chain with .ValidateOnStart() for automatic startup validation.
1. Define Your Options Class with Nested Validator
using FluentValidation;
public class DatabaseOptions
{
  public string ConnectionString { get; set; } = string.Empty;
  public int MaxRetries { get; set; }
  public int CommandTimeout { get; set; }
  // Nested validator - sealed and only used here
  public sealed class Validator : AbstractValidator<DatabaseOptions>
  {
    public Validator()
    {
      RuleFor(x => x.ConnectionString)
        .NotEmpty()
        .WithMessage("Database connection string is required");
      RuleFor(x => x.MaxRetries)
        .GreaterThan(0)
        .LessThanOrEqualTo(10)
        .WithMessage("MaxRetries must be between 1 and 10");
      RuleFor(x => x.CommandTimeout)
        .GreaterThanOrEqualTo(30)
        .WithMessage("CommandTimeout must be at least 30 seconds");
    }
  }
}
2. Register with Automatic Startup Validation
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register options with automatic startup validation
builder.Services
  .AddFluentValidatedOptions<DatabaseOptions, DatabaseOptions.Validator>(builder.Configuration)
  .ValidateOnStart(); // ✅ Validates when host starts, throws on error
var app = builder.Build();
app.Run(); // Validation happens automatically before this runs
What this does:
- Binds the DatabaseOptionssection from appsettings.json
- Registers the FluentValidation validator
- Validates configuration at startup (before app.Run())
- Fails fast with clear error messages if configuration is invalid
- No manual validation calls needed!
Configuration Binding
The library automatically discovers which configuration section to bind based on simple, predictable rules.
Default: Class Name
By default, the library uses the class name as the configuration section name:
public class DatabaseOptions
{
  public string ConnectionString { get; set; } = string.Empty;
  // ...
}
Binds to "DatabaseOptions" section:
{
  "DatabaseOptions": {
    "ConnectionString": "Server=localhost;Database=myapp;",
    "MaxRetries": 3,
    "CommandTimeout": 30
  }
}
// Automatically binds to "DatabaseOptions" section
services
  .AddFluentValidatedOptions<DatabaseOptions, DatabaseOptions.Validator>(configuration)
  .ValidateOnStart();
Custom Configuration Key with [ConfigurationKey] Attribute
Override the default by decorating your options class with [ConfigurationKey]:
Simple Configuration Key:
using TimeWarp.OptionsValidation;
[ConfigurationKey("Database")]
public class DatabaseOptions
{
  public string ConnectionString { get; set; } = string.Empty;
  // ...
}
Binds to "Database" section:
{
  "Database": {
    "ConnectionString": "Server=localhost;Database=myapp;",
    "MaxRetries": 3,
    "CommandTimeout": 30
  }
}
Hierarchical Key with Colon Separator:
[ConfigurationKey("MyApp:Settings:Database")]
public class DatabaseOptions
{
  public string ConnectionString { get; set; } = string.Empty;
  // ...
}
Binds to nested "MyApp" → "Settings" → "Database" path:
{
  "MyApp": {
    "Settings": {
      "Database": {
        "ConnectionString": "Server=localhost;Database=myapp;",
        "MaxRetries": 3,
        "CommandTimeout": 30
      }
    }
  }
}
// Automatically binds to configuration key specified in attribute
services
  .AddFluentValidatedOptions<DatabaseOptions, DatabaseOptions.Validator>(configuration)
  .ValidateOnStart();
Advanced: Manual Section Binding
For dynamic section paths or complex scenarios not covered by the attribute:
// Manual binding for runtime-determined paths
string environment = builder.Environment.EnvironmentName;
services.AddOptions<DatabaseOptions>()
  .Bind(configuration.GetSection($"{environment}:Database"))
  .ValidateFluentValidation<DatabaseOptions, DatabaseOptions.Validator>()
  .ValidateOnStart();
Automatic Configuration Key Resolution Summary:
- ✅ Uses class name: DatabaseOptions→"DatabaseOptions"
- ✅ Simple override: [ConfigurationKey("Database")]→"Database"
- ✅ Hierarchical paths: [ConfigurationKey("MyApp:Settings:Database")]→"MyApp" → "Settings" → "Database"
- ❌ Does NOT trim suffixes like "Options" automatically
- ❌ Does NOT pluralize names automatically
Programmatic Configuration
You can also configure options programmatically without IConfiguration:
services
  .AddFluentValidatedOptions<DatabaseOptions, DatabaseOptions.Validator>(options =>
  {
    options.ConnectionString = "Server=localhost;Database=myapp;";
    options.MaxRetries = 3;
    options.CommandTimeout = 30;
  })
  .ValidateOnStart();
Complete Startup Example
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register multiple validated options with automatic startup validation
builder.Services
  .AddFluentValidatedOptions<DatabaseOptions, DatabaseOptions.Validator>(builder.Configuration)
  .ValidateOnStart();
builder.Services
  .AddFluentValidatedOptions<CacheOptions, CacheOptions.Validator>(builder.Configuration)
  .ValidateOnStart();
builder.Services
  .AddFluentValidatedOptions<EmailOptions, EmailOptions.Validator>(builder.Configuration)
  .ValidateOnStart();
var app = builder.Build();
app.Run(); // All options validated before this runs
If any configuration is invalid, the application will fail to start with clear error messages indicating exactly which settings are invalid and why.
Without Startup Validation
If you don't need automatic startup validation, simply omit .ValidateOnStart():
// Validates on first access instead of at startup
services.AddFluentValidatedOptions<DatabaseOptions, DatabaseOptions.Validator>(configuration);
// No .ValidateOnStart() call - validation happens lazily
This approach validates options when they're first accessed rather than at application startup.
Features
- Automatic Startup Validation: Use .ValidateOnStart()to fail fast on invalid configuration
- Automatic Key Discovery: Uses the class name as the configuration key by default
- Custom Key Mapping: Use [ConfigurationKey]attribute to override the configuration key
- Hierarchical Keys: Support for nested configuration paths using colon separators
- Seamless Integration: Works with Microsoft.Extensions.Options infrastructure and OptionsBuilder<T>
- FluentValidation Power: Rich validation rules, custom validators, conditional validation
- Clear Error Messages: Detailed, actionable error messages from FluentValidation
- Type Safety: Strongly-typed options with compile-time checking
- Flexible API: Choose between fluent API (with .ValidateOnStart()) or simple registration
Releases
See the Release Notes
Unlicense
Contributing
Time is of the essence. Before developing a Pull Request I recommend opening a discussion.
Please feel free to make suggestions and help out with the documentation. Please refer to Markdown for how to write markdown files.
Contact
Sometimes the github notifications get lost in the shuffle. If you file an issue and don't get a response in a timely manner feel free to ping on our Discord server.
| Product | Versions 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. | 
- 
                                                    net10.0- FluentValidation (>= 12.0.0)
- Microsoft.Extensions.DependencyInjection (>= 9.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.10)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 9.0.10)
- TimeWarp.Build.Tasks (>= 1.0.0)
- TimeWarp.SourceGenerators (>= 1.0.0-beta.7)
 
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.0-beta.3 | 36 | 10/25/2025 | 
| 1.0.0-beta.2 | 97 | 5/18/2024 | 
| 1.0.0-beta.1 | 58 | 5/18/2024 | 
| 1.0.0-alpha.2 | 489 | 11/9/2022 | 
| 1.0.0-alpha.1 | 72 | 11/9/2022 |