SkyWebFramework.Configuration 1.0.1

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

🚀 SkyWebFramework.Configuration

A powerful, feature-rich .NET configuration library that simplifies configuration management with validation, type safety, change tracking, and persistence capabilities.

NuGet Downloads License: MIT

✨ Features

🎯 Core Capabilities

  • Easy Configuration Binding - Bind POCO classes to configuration sections with one line
  • Automatic Validation - DataAnnotations validation with detailed error messages
  • Type-Safe Access - Strongly-typed configuration with compile-time safety
  • Multiple Lifetimes - Support for Singleton, Scoped, and Transient services
  • Environment Overrides - Environment-specific configuration sections

🔄 Advanced Features

  • Property-Level Change Tracking - Monitor specific property changes with callbacks
  • Change History - Keep historical records of configuration changes
  • Configuration Snapshots - Create immutable snapshots for comparison/rollback
  • Persistent Storage - Store changes and snapshots to file or database
  • Reload on Change - Automatic configuration reloading with IOptionsMonitor

🛠️ Utility Extensions

  • Simple Key Access - Type-safe methods for single configuration values
  • Validation Helpers - Built-in validators for common patterns
  • Type Converters - Parse booleans, enums, URIs, TimeSpans, arrays, and more
  • Custom Validation - Support for custom validation functions

📦 Installation

dotnet add package SkyWebFramework.Configuration

Or via NuGet Package Manager:

Install-Package SkyWebFramework.Configuration

🚀 Quick Start

1. Basic Configuration Binding

// Configuration class
public class AppSettings
{
    [Required]
    public string ApplicationName { get; set; }
    
    [Range(1, 100)]
    public int MaxConnections { get; set; }
    
    [EmailAddress]
    public string AdminEmail { get; set; }
}

// In appsettings.json
{
  "AppSettings": {
    "ApplicationName": "MyApp",
    "MaxConnections": 50,
    "AdminEmail": "admin@example.com"
  }
}

// Register in Startup/Program.cs
builder.Services.AddEasyConfig<AppSettings>(builder.Configuration);

// Use in your code
public class MyService
{
    private readonly AppSettings _settings;
    
    public MyService(AppSettings settings)
    {
        _settings = settings;
    }
}

2. Simple Key-Value Access

// Get required values
var apiKey = configuration.GetRequiredValue<string>("ApiKey");
var timeout = configuration.GetRequiredValue<int>("Timeout");

// Get with defaults
var retryCount = configuration.GetValueOrDefault("RetryCount", 3);
var isEnabled = configuration.GetBool("FeatureFlag", defaultValue: true);

// Get validated values
var port = configuration.GetValidatedValue("Port", 
    value => value > 0 && value < 65536, 
    "Port must be between 1 and 65535");

// Connection strings
var connString = configuration.GetRequiredConnectionString("DefaultConnection");

3. Type Conversion Extensions

// Boolean parsing (supports: true/false, yes/no, 1/0, on/off, enabled/disabled)
var isDebug = configuration.GetBool("Debug");

// Integer with validation
var maxSize = configuration.GetInt("MaxSize", defaultValue: 100, minValue: 1, maxValue: 1000);

// Enums
var logLevel = configuration.GetEnum<LogLevel>("LogLevel", LogLevel.Information);

// TimeSpan
var timeout = configuration.GetTimeSpan("Timeout", TimeSpan.FromSeconds(30));

// URI
var apiUrl = configuration.GetRequiredUri("ApiEndpoint");

// Arrays and Lists
var allowedHosts = configuration.GetStringArray("AllowedHosts", separator: ";");
var ports = configuration.GetList<int>("Ports");

🎯 Advanced Usage

Configuration Options

builder.Services.AddEasyConfig<AppSettings>(
    builder.Configuration,
    sectionName: "MyApp",
    options =>
    {
        options.Validate = true;                      // Enable validation
        options.RequireSection = true;                // Throw if section missing
        options.ReloadOnChange = true;                // Auto-reload on file changes
        options.EnableChangeTracking = true;          // Track property changes
        options.ChangeHistorySize = 50;              // Keep 50 changes in history
        options.AutoCreateSection = false;            // Don't auto-create missing sections
        options.EnvironmentSuffix = "Development";    // Use "MyApp:Development" section
        options.Lifetime = ServiceLifetime.Singleton; // Service lifetime
    });

Change Tracking

// Register config with change tracking
builder.Services.AddEasyConfig<AppSettings>(
    builder.Configuration,
    options => 
    {
        options.ReloadOnChange = true;
        options.EnableChangeTracking = true;
    });

// Subscribe to changes
public class ConfigMonitorService
{
    public ConfigMonitorService(IConfigChangeManager<AppSettings> changeManager)
    {
        // Track specific property changes
        changeManager.OnPropertyChange("MaxConnections", change =>
        {
            Console.WriteLine($"MaxConnections changed from {change.OldValue} to {change.NewValue}");
        });
        
        // Track all changes
        changeManager.OnAnyChange(change =>
        {
            Console.WriteLine($"{change.PropertyName} changed at {change.ChangedAt}");
        });
        
        // Get change history
        var history = changeManager.GetChangeHistory("MaxConnections", count: 10);
    }
}

Configuration Snapshots

// Create a snapshot
var snapshot = configuration.CreateSnapshot<AppSettings>("before-deployment");
Console.WriteLine($"Snapshot created at {snapshot.CapturedAt}");

// Compare with current config
var current = configuration.GetEasyConfig<AppSettings>();
// ... compare snapshot.Value with current ...

Persistent Storage (Advanced)

Option 1: JSON File Storage
builder.Services.AddPersistentConfig<AppSettings>(
    builder.Configuration,
    options =>
    {
        options.EnablePersistence = true;
        options.PersistencePath = "config-history"; // Optional: custom path
        options.AutoPersistChanges = true;
        options.ReloadOnChange = true;
        options.EnableChangeTracking = true;
    });
Option 2: Database Storage
// Add DbContext
builder.Services.AddDbContext<ConfigDbContext>(options =>
    options.UseSqlServer(connectionString));

// Register with database persistence
builder.Services.AddPersistentConfig<AppSettings>(
    builder.Configuration,
    options =>
    {
        options.EnablePersistence = true;
        options.PersistenceStore = new DatabasePersistenceStore(serviceProvider);
        options.AutoPersistChanges = true;
    });

// Query historical changes
public class ConfigAuditService
{
    private readonly IPersistentConfigChangeManager<AppSettings> _changeManager;
    
    public async Task<IEnumerable<ConfigChangeInfo<AppSettings>>> GetAuditTrail()
    {
        return await _changeManager.GetPersistedChangesAsync(
            "MaxConnections",
            startDate: DateTime.UtcNow.AddDays(-30),
            maxResults: 100
        );
    }
}

Environment-Specific Configuration

// appsettings.json
{
  "AppSettings": {
    "ApiUrl": "https://api.example.com",
    "Development": {
      "ApiUrl": "https://dev-api.example.com"
    },
    "Production": {
      "ApiUrl": "https://prod-api.example.com"
    }
  }
}

// Register with environment override
builder.Services.AddEasyConfig<AppSettings>(
    builder.Configuration,
    options => 
    {
        options.EnvironmentSuffix = builder.Environment.EnvironmentName;
    });

Custom Validation

builder.Services.AddEasyConfig<AppSettings>(
    builder.Configuration,
    options =>
    {
        options.CustomValidator = config =>
        {
            var settings = (AppSettings)config;
            if (settings.MaxConnections > 100 && !settings.IsPremium)
            {
                throw new InvalidOperationException(
                    "MaxConnections over 100 requires premium subscription");
            }
        };
    });

🔧 Extension Methods Reference

Configuration Extensions

Method Description
AddEasyConfig<T>() Register configuration with full options
TryAddEasyConfig<T>() Register only if not already registered
GetEasyConfig<T>() Get configuration instance directly
CreateSnapshot<T>() Create configuration snapshot
ValidateEasyConfigs() Validate multiple configurations

Simple Key Extensions

Method Description
GetRequiredValue<T>() Get value or throw
GetValueOrDefault<T>() Get value with default fallback
GetValidatedValue<T>() Get and validate value
GetRequiredConnectionString() Get connection string or throw
GetBool() Parse boolean with common formats
GetInt() Parse integer with min/max validation
GetDouble() Parse double with min/max validation
GetTimeSpan() Parse TimeSpan
GetEnum<T>() Parse enum value
GetUri() Parse URI with validation
GetRequiredUri() Parse required URI
GetStringArray() Split string to array
GetList<T>() Split and convert to typed list
GetSectionAsDictionary() Get section as dictionary
HasValue() Check if key exists

Persistence Extensions

Method Description
AddPersistentConfig<T>() Register with persistent storage
CreateAndPersistSnapshot<T>() Create and save snapshot
GetPersistedSnapshot<T>() Retrieve saved snapshot

🏗️ Configuration Classes

Exceptions

try
{
    var config = configuration.GetEasyConfig<AppSettings>();
}
catch (ConfigValidationException ex)
{
    Console.WriteLine($"Validation failed for {ex.Section}");
    foreach (var error in ex.ValidationErrors)
    {
        Console.WriteLine($"  - {error.ErrorMessage}");
    }
}
catch (ConfigSectionMissingException ex)
{
    Console.WriteLine($"Missing section: {ex.Section}");
}

Change Info

public class ConfigChangeInfo<T>
{
    public string PropertyName { get; set; }
    public object? OldValue { get; set; }
    public object? NewValue { get; set; }
    public DateTime ChangedAt { get; set; }
    public T CurrentConfig { get; set; }
}

Snapshot

public interface IConfigSnapshot<T>
{
    T Value { get; }
    DateTime CapturedAt { get; }
    string Label { get; }
}

📋 Complete Example

using SkyWebFramework.Configuration;

var builder = WebApplication.CreateBuilder(args);

// 1. Simple registration
builder.Services.AddEasyConfig<DatabaseSettings>(builder.Configuration);

// 2. Advanced registration with all features
builder.Services.AddPersistentConfig<AppSettings>(
    builder.Configuration,
    options =>
    {
        options.Validate = true;
        options.ReloadOnChange = true;
        options.EnableChangeTracking = true;
        options.EnablePersistence = true;
        options.ChangeHistorySize = 100;
        options.EnvironmentSuffix = builder.Environment.EnvironmentName;
        options.CustomValidator = config =>
        {
            var settings = (AppSettings)config;
            // Custom validation logic
        };
    });

var app = builder.Build();

// 3. Use in controllers/services
public class MyController : ControllerBase
{
    private readonly AppSettings _settings;
    private readonly IConfigChangeManager<AppSettings> _changeManager;
    
    public MyController(
        AppSettings settings,
        IConfigChangeManager<AppSettings> changeManager)
    {
        _settings = settings;
        _changeManager = changeManager;
        
        // Subscribe to changes
        _changeManager.OnPropertyChange("ApiUrl", change =>
        {
            _logger.LogInformation(
                "API URL changed from {Old} to {New}", 
                change.OldValue, 
                change.NewValue);
        });
    }
    
    [HttpGet("config")]
    public IActionResult GetConfig()
    {
        return Ok(new
        {
            Current = _settings,
            History = _changeManager.GetChangeHistory("ApiUrl", 10)
        });
    }
}

🎨 Best Practices

1. Use DataAnnotations for Validation

public class ApiSettings
{
    [Required]
    [Url]
    public string BaseUrl { get; set; }
    
    [Required]
    [Range(1, 3600)]
    public int TimeoutSeconds { get; set; }
    
    [Required]
    [RegularExpression(@"^[a-zA-Z0-9-]+$")]
    public string ApiKey { get; set; }
}

2. Organize Configuration by Feature

// Instead of one large class
public class EmailSettings { }
public class CacheSettings { }
public class LoggingSettings { }

// Register separately
services.AddEasyConfig<EmailSettings>(configuration);
services.AddEasyConfig<CacheSettings>(configuration);
services.AddEasyConfig<LoggingSettings>(configuration);

3. Use Environment-Specific Sections

{
  "Email": {
    "SmtpServer": "smtp.example.com",
    "Development": {
      "SmtpServer": "localhost"
    },
    "Production": {
      "SmtpServer": "smtp.production.com"
    }
  }
}

4. Monitor Critical Configuration Changes

changeManager.OnPropertyChange("DatabaseConnectionString", change =>
{
    _logger.LogWarning(
        "⚠️ Database connection changed! Old: {Old}, New: {New}",
        MaskConnectionString(change.OldValue?.ToString()),
        MaskConnectionString(change.NewValue?.ToString()));
    
    // Optionally trigger reconnection logic
    _dbContext.Database.CloseConnection();
});

5. Create Snapshots Before Deployments

// In deployment script
var snapshot = await configuration.CreateAndPersistSnapshot<AppSettings>(
    $"pre-deployment-{DateTime.UtcNow:yyyy-MM-dd-HH-mm}",
    persistenceStore);

🔍 Troubleshooting

Configuration Not Loading

// Verify section exists
var section = configuration.GetSection("AppSettings");
if (!section.Exists())
{
    Console.WriteLine("Section does not exist!");
}

// Check for case sensitivity
// "appsettings" vs "AppSettings"

Validation Failing

try
{
    services.AddEasyConfig<AppSettings>(configuration);
}
catch (ConfigValidationException ex)
{
    foreach (var error in ex.ValidationErrors)
    {
        Console.WriteLine($"{error.MemberNames.First()}: {error.ErrorMessage}");
    }
}

Change Tracking Not Working

// Ensure ReloadOnChange is enabled
options.ReloadOnChange = true;
options.EnableChangeTracking = true;

// File must exist in config sources
builder.Configuration.AddJsonFile("appsettings.json", 
    optional: false, 
    reloadOnChange: true);

📚 Additional Resources

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

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

💬 Support

🌟 Features Roadmap

  • Azure Key Vault integration
  • Configuration encryption at rest
  • Real-time configuration dashboard
  • Configuration A/B testing support
  • Multi-tenant configuration management
  • GraphQL API for configuration queries

Made with ❤️ by the SkyWebFramework Team

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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
1.0.1 160 11/8/2025

v1.0.0:
- Initial release
- Property-level change tracking with callbacks
- Configuration snapshots for rollback/comparison
- Persistent storage (JSON file and database)
- 20+ simple key-value extension methods
- Environment-specific configuration overrides
- Comprehensive DataAnnotations validation
- Change history with configurable retention
- Type-safe configuration access