https://github.com/timewarpengineering/timewarp-options-validation
https://github.com/timewarpengineering/timewarp-options-validation
Last synced: about 1 month ago
JSON representation
- Host: GitHub
- URL: https://github.com/timewarpengineering/timewarp-options-validation
- Owner: TimeWarpEngineering
- License: unlicense
- Created: 2022-11-09T03:09:36.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2025-12-06T10:11:12.000Z (4 months ago)
- Last Synced: 2025-12-10T01:57:44.091Z (3 months ago)
- Language: C#
- Size: 134 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- License: license
Awesome Lists containing this project
README
[](https://dotnet.microsoft.com)
[](https://github.com/TimeWarpEngineering/timewarp-options-validation)
[](https://discord.gg/7F4bS2T)
[](https://github.com/TimeWarpEngineering/timewarp-options-validation/actions)
[](https://www.nuget.org/packages/TimeWarp.OptionsValidation/)
[](https://www.nuget.org/packages/TimeWarp.OptionsValidation/)
[](https://github.com/TimeWarpEngineering/timewarp-options-validation/issues)
[](https://github.com/TimeWarpEngineering/timewarp-options-validation)
[](https://github.com/TimeWarpEngineering/timewarp-options-validation/issues)
[](https://twitter.com/intent/tweet?url=https://github.com/TimeWarpEngineering/timewarp-options-validation)
[](https://twitter.com/intent/follow?screen_name=StevenTCramer)
[](https://twitter.com/intent/follow?screen_name=TheFreezeTeam1)
# 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! :star:
If you like or are using this project please give it a star. Thank you!
## Installation
```console
dotnet add package TimeWarp.OptionsValidation
```
You can see the latest NuGet packages from the official [TimeWarp NuGet page](https://www.nuget.org/profiles/TimeWarp.Enterprises).
* [TimeWarp.OptionsValidation](https://www.nuget.org/packages/TimeWarp.OptionsValidation/) [](https://www.nuget.org/packages/TimeWarp.OptionsValidation/)
## Usage
### Basic Setup with Automatic Startup Validation
Use `AddFluentValidatedOptions()` which returns `OptionsBuilder`, allowing you to chain with `.ValidateOnStart()` for automatic startup validation.
#### 1. Define Your Options Class with Nested Validator
```csharp
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
{
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
```csharp
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register options with automatic startup validation
builder.Services
.AddFluentValidatedOptions(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 `DatabaseOptions` section 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:
```csharp
public class DatabaseOptions
{
public string ConnectionString { get; set; } = string.Empty;
// ...
}
```
Binds to `"DatabaseOptions"` section:
```json
{
"DatabaseOptions": {
"ConnectionString": "Server=localhost;Database=myapp;",
"MaxRetries": 3,
"CommandTimeout": 30
}
}
```
```csharp
// Automatically binds to "DatabaseOptions" section
services
.AddFluentValidatedOptions(configuration)
.ValidateOnStart();
```
#### Custom Configuration Key with `[ConfigurationKey]` Attribute
Override the default by decorating your options class with `[ConfigurationKey]`:
**Simple Configuration Key:**
```csharp
using TimeWarp.OptionsValidation;
[ConfigurationKey("Database")]
public class DatabaseOptions
{
public string ConnectionString { get; set; } = string.Empty;
// ...
}
```
Binds to `"Database"` section:
```json
{
"Database": {
"ConnectionString": "Server=localhost;Database=myapp;",
"MaxRetries": 3,
"CommandTimeout": 30
}
}
```
**Hierarchical Key with Colon Separator:**
```csharp
[ConfigurationKey("MyApp:Settings:Database")]
public class DatabaseOptions
{
public string ConnectionString { get; set; } = string.Empty;
// ...
}
```
Binds to nested `"MyApp" → "Settings" → "Database"` path:
```json
{
"MyApp": {
"Settings": {
"Database": {
"ConnectionString": "Server=localhost;Database=myapp;",
"MaxRetries": 3,
"CommandTimeout": 30
}
}
}
}
```
```csharp
// Automatically binds to configuration key specified in attribute
services
.AddFluentValidatedOptions(configuration)
.ValidateOnStart();
```
#### Advanced: Manual Section Binding
For dynamic section paths or complex scenarios not covered by the attribute:
```csharp
// Manual binding for runtime-determined paths
string environment = builder.Environment.EnvironmentName;
services.AddOptions()
.Bind(configuration.GetSection($"{environment}:Database"))
.ValidateFluentValidation()
.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:
```csharp
services
.AddFluentValidatedOptions(options =>
{
options.ConnectionString = "Server=localhost;Database=myapp;";
options.MaxRetries = 3;
options.CommandTimeout = 30;
})
.ValidateOnStart();
```
### Complete Startup Example
```csharp
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register multiple validated options with automatic startup validation
builder.Services
.AddFluentValidatedOptions(builder.Configuration)
.ValidateOnStart();
builder.Services
.AddFluentValidatedOptions(builder.Configuration)
.ValidateOnStart();
builder.Services
.AddFluentValidatedOptions(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()`:
```csharp
// Validates on first access instead of at startup
services.AddFluentValidatedOptions(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`
- **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](./documentation/releases.md)
## Unlicense
[](https://unlicense.org)
## Contributing
Time is of the essence. Before developing a Pull Request I recommend opening a [discussion](https://github.com/TimeWarpEngineering/timewarp-options-validation/discussions).
Please feel free to make suggestions and help out with the [documentation](https://timewarpengineering.github.io/timewarp-options-validation/).
Please refer to [Markdown](http://daringfireball.net/projects/markdown/) for how to write markdown files.
## Contact
Sometimes the github notifications get lost in the shuffle. If you file an [issue](https://github.com/TimeWarpEngineering/timewarp-options-validation/issues) and don't get a response in a timely manner feel free to ping on our [Discord server](https://discord.gg/A55JARGKKP).
[](https://discord.gg/7F4bS2T)