Fox.ConfigKit.ResultKit
1.0.3
See the version list below for details.
dotnet add package Fox.ConfigKit.ResultKit --version 1.0.3
NuGet\Install-Package Fox.ConfigKit.ResultKit -Version 1.0.3
<PackageReference Include="Fox.ConfigKit.ResultKit" Version="1.0.3" />
<PackageVersion Include="Fox.ConfigKit.ResultKit" Version="1.0.3" />
<PackageReference Include="Fox.ConfigKit.ResultKit" />
paket add Fox.ConfigKit.ResultKit --version 1.0.3
#r "nuget: Fox.ConfigKit.ResultKit, 1.0.3"
#:package Fox.ConfigKit.ResultKit@1.0.3
#addin nuget:?package=Fox.ConfigKit.ResultKit&version=1.0.3
#tool nuget:?package=Fox.ConfigKit.ResultKit&version=1.0.3
Fox.ConfigKit.ResultKit
Integration package combining Fox.ConfigKit configuration validation with Fox.ResultKit Railway Oriented Programming
This package bridges Fox.ConfigKit's configuration validation with Fox.ResultKit's Result pattern, enabling functional-style configuration validation workflows.
Installation
dotnet add package Fox.ConfigKit.ResultKit
NuGet Package Manager:
Install-Package Fox.ConfigKit.ResultKit
PackageReference:
<PackageReference Include="Fox.ConfigKit.ResultKit" Version="1.0.0" />
Core Concepts
Configuration Validation with Result Pattern
Validate configurations and return Result<T> for functional composition:
using Fox.ConfigKit.ResultKit;
using Fox.ResultKit;
// Standalone validation without dependency injection
var result = ConfigValidator.Validate<DatabaseConfig>()
.NotEmpty(c => c.ConnectionString, "Connection string is required")
.InRange(c => c.MaxPoolSize, 1, 1000, "Max pool size must be between 1 and 1000")
.ToResult(databaseConfig);
// Chain with other operations
var finalResult = result
.Bind(config => DatabaseService.Connect(config))
.Bind(connection => connection.ExecuteQuery())
.Match(
onSuccess: data => $"Query returned {data.Count} records",
onFailure: error => $"Failed: {error}"
);
Note: ConfigValidator.Validate<T>() is useful for:
- Console applications without dependency injection
- Unit tests requiring standalone validation
- Functional composition with other Result-based operations
- Scripts or utilities that need configuration validation
For ASP.NET Core applications with DI, use AddConfigKit<T>() with ValidateOnStartup() instead.
Startup Validation with Result
Validate configurations at startup and handle failures gracefully:
var configValidation = ConfigValidator.Validate<ApiConfig>()
.NotEmpty(c => c.BaseUrl, "API URL is required")
.NotEmpty(c => c.ApiKey, "API key is required")
.ToResult(apiConfig);
if (configValidation.IsFailure)
{
var errors = configValidation.Error;
throw new InvalidOperationException($"Configuration validation failed: {errors}");
}
Key Usage Patterns
Functional Configuration Validation
using Fox.ConfigKit.ResultKit;
using Fox.ResultKit;
public Result<AppConfig> ValidateAppConfiguration(AppConfig config)
{
return ConfigValidator.Validate<AppConfig>()
.NotEmpty(c => c.Name, "Application name is required")
.MatchesPattern(c => c.Version, @"^\d+\.\d+\.\d+$", "Version must be X.Y.Z format")
.InRange(c => c.Port, 1, 65535, "Port must be between 1 and 65535")
.ToResult(config);
}
// Usage with Railway Oriented Programming
var result = ValidateAppConfiguration(appConfig)
.Bind(config => InitializeApplication(config))
.Bind(app => app.Start())
.Match(
onSuccess: app => $"Application {app.Name} started successfully",
onFailure: error => $"Startup failed: {error}"
);
Conditional Validation with Results
public Result<SecurityConfig> ValidateSecurityConfig(SecurityConfig config, string environment)
{
var builder = ConfigValidator.Validate<SecurityConfig>()
.NotEmpty(c => c.Environment, "Environment is required");
if (environment == "Production")
{
builder = builder
.NotEmpty(c => c.CertificatePath, "Certificate is required in production")
.FileExists(c => c.CertificatePath, message: "Certificate file not found");
}
return builder.ToResult(config);
}
Aggregating Multiple Configuration Results
public Result<AppSettings> ValidateAllConfigurations(
DatabaseConfig dbConfig,
ApiConfig apiConfig,
LoggingConfig loggingConfig)
{
var dbResult = ConfigValidator.Validate<DatabaseConfig>()
.NotEmpty(c => c.ConnectionString, "DB connection string is required")
.ToValidationResult(dbConfig);
var apiResult = ConfigValidator.Validate<ApiConfig>()
.NotEmpty(c => c.BaseUrl, "API URL is required")
.ToValidationResult(apiConfig);
var loggingResult = ConfigValidator.Validate<LoggingConfig>()
.DirectoryExists(c => c.LogDirectory, message: "Log directory not found")
.ToValidationResult(loggingConfig);
// Fail-fast: stop at first error
return dbResult
.Bind(() => apiResult)
.Bind(() => loggingResult)
.Bind(() => Result<AppSettings>.Success(new AppSettings(dbConfig, apiConfig, loggingConfig)));
}
Common Scenarios
Startup Validation Pipeline
var startupResult = ConfigValidator.Validate<DatabaseConfig>()
.NotEmpty(c => c.ConnectionString, "Connection string is required")
.InRange(c => c.MaxPoolSize, 1, 1000, "Max pool size must be between 1 and 1000")
.ToResult(dbConfig)
.BindAsync(config => DatabaseService.TestConnection(config))
.BindAsync(connection => MigrationService.EnsureSchemaUpToDate(connection))
.Match(
onSuccess: _ => "Database ready",
onFailure: error => throw new InvalidOperationException($"Startup failed: {error}")
);
Environment-Specific Validation
public Result<SecurityConfig> ValidateForEnvironment(SecurityConfig config, IHostEnvironment env)
{
var validator = ConfigValidator.Validate<SecurityConfig>();
if (env.IsProduction())
{
validator = validator
.NotEmpty(c => c.CertificatePath, "Certificate is required in production")
.FileExists(c => c.CertificatePath, message: "Certificate not found")
.NoPlainTextSecrets(c => c.ApiKey, "Plain-text secrets not allowed in production");
}
else if (env.IsDevelopment())
{
validator = validator
.NotEmpty(c => c.ApiKey, "API key is required");
}
return validator.ToResult(config);
}
Collecting All Errors
// Use ToErrorsResult() to collect all validation errors instead of stopping at first error
var validationResult = ConfigValidator.Validate<AppConfig>()
.NotEmpty(c => c.Name, "Name is required")
.InRange(c => c.Port, 1, 65535, "Invalid port")
.NotEmpty(c => c.ApiKey, "API key is required")
.ToErrorsResult(config);
if (validationResult.IsFailure)
{
foreach (var error in validationResult.Errors)
{
Console.WriteLine($"Validation error: {error}");
}
}
When to Use Fox.ConfigKit.ResultKit
Use Fox.ConfigKit.ResultKit when:
- You're already using Fox.ResultKit for Railway Oriented Programming
- You want functional-style configuration validation
- You need to compose configuration validation with other Result-based operations
- You want to aggregate multiple configuration validation results
- You prefer explicit error handling over exceptions
- You want to chain configuration validation with application startup logic
Don't use Fox.ConfigKit.ResultKit when:
- You don't use Fox.ResultKit or Result pattern
- You prefer exception-based error handling
- You only need simple startup validation (use Fox.ConfigKit directly with
ValidateOnStartup) - You're not familiar with Railway Oriented Programming
Standalone vs. DI Usage
Standalone Validation (ConfigValidator)
Use ConfigValidator.Validate<T>() for:
// Console applications
static void Main(string[] args)
{
var config = LoadConfiguration();
var result = ConfigValidator.Validate<AppConfig>()
.NotEmpty(c => c.Name, "Name is required")
.ToResult(config);
if (result.IsFailure)
{
Console.WriteLine($"Config error: {result.Error}");
return;
}
}
// Unit tests
[Fact]
public void Configuration_should_be_valid()
{
var config = new DatabaseConfig { ConnectionString = "..." };
var result = ConfigValidator.Validate<DatabaseConfig>()
.NotEmpty(c => c.ConnectionString, "Required")
.ToResult(config);
result.IsSuccess.Should().BeTrue();
}
// Functional composition
public Result<Database> InitializeDatabase(DatabaseConfig config)
{
return ConfigValidator.Validate<DatabaseConfig>()
.NotEmpty(c => c.ConnectionString, "Connection string required")
.ToResult(config)
.Bind(cfg => Database.Connect(cfg));
}
DI-Based Validation (AddConfigKit)
Use AddConfigKit<T>() with ValidateOnStartup() for ASP.NET Core:
// ASP.NET Core applications with dependency injection
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddConfigKit<DatabaseConfig>("Database")
.NotEmpty(c => c.ConnectionString, "Connection string is required")
.InRange(c => c.MaxPoolSize, 1, 1000, "Pool size must be between 1 and 1000")
.ValidateOnStartup();
var app = builder.Build(); // Validation happens here (fail-fast)
app.Run();
Key Differences:
| Feature | ConfigValidator.Validate<T>() |
AddConfigKit<T>() |
|---|---|---|
| Use Case | Standalone, functional, testing | ASP.NET Core with DI |
| Returns | ConfigValidationBuilder<T> |
ConfigValidationBuilder<T> |
| Validation Timing | Explicit (when you call .ToResult()) |
Automatic at startup |
| Result Type | Result<T>, ErrorsResult |
Exception on failure |
| DI Required | No | Yes |
| IOptions Integration | No | Yes |
Related Packages
- Fox.ConfigKit - Core configuration validation library
- Fox.ResultKit - Lightweight Result pattern library for Railway Oriented Programming
Full Documentation
For comprehensive documentation, advanced scenarios, and API reference, see the GitHub repository.
License
This project is licensed under the MIT License - see the LICENSE.txt file for details.
Author
Kroly Akcz
- GitHub: @akikari
- Repository: Fox.ConfigKit
Acknowledgments
Inspired by:
- Railway Oriented Programming by Scott Wlaschin - Functional error handling principles
- F# Result Type - The foundation for functional error handling
- Options Pattern - Microsoft's recommended approach for configuration
| Product | Versions 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 is compatible. 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 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
- Fox.ConfigKit (>= 1.0.3)
- Fox.ResultKit (>= 1.2.0)
-
net8.0
- Fox.ConfigKit (>= 1.0.3)
- Fox.ResultKit (>= 1.2.0)
-
net9.0
- Fox.ConfigKit (>= 1.0.3)
- Fox.ResultKit (>= 1.2.0)
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.4 | 36 | 2/14/2026 |
Version 1.0.3: Fix NuGet package README - use project README instead of root (removes emoji from H1 for NuGet.org compatibility).