codewithmukesh/dotnet-claude-kit

configuration

Configuration patterns for .NET 10 applications.

View source

How to use

  1. Copy the installation command and review the source package before installing it in your own agent environment.
  2. Check the source document for required tools, credentials and supported hosts.
  3. Describe your input and desired deliverable; review the output against the source material.
npx skills add https://github.com/codewithmukesh/dotnet-claude-kit --skill configuration

Before you start

  • Installation does not include a model subscription, API allowance or permission to access your files.
  • Repository stars and installation counts describe activity, not an independent quality or security test.
Original skill document

Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.

Configuration

Core Principles

  1. Options pattern always — Never read IConfiguration directly in services. Bind configuration sections to strongly-typed classes with validation.
  2. Validate on startup — Use ValidateDataAnnotations() and ValidateOnStart() to catch misconfiguration before the first request.
  3. Secrets never in source — Use user secrets in development, Azure Key Vault or environment variables in production. Never commit secrets to git.
  4. Configuration layering — appsettings.json → appsettings.{Environment}.json → environment variables → user secrets. Later sources override earlier ones.

Patterns

Options Pattern

csharp
// Options class with validation attributes
public class DatabaseOptions
{
    public const string SectionName = "Database";

    [Required]
    public required string ConnectionString { get; init; }

    [Range(1, 100)]
    public int MaxRetryCount { get; init; } = 3;

    [Range(1, 60)]
    public int CommandTimeoutSeconds { get; init; } = 30;
}

// Registration with validation
builder.Services.AddOptions<DatabaseOptions>()
    .BindConfiguration(DatabaseOptions.SectionName)
    .ValidateDataAnnotations()
    .ValidateOnStart(); // Fails at startup if configuration is invalid
json
// appsettings.json
{
  "Database": {
    "ConnectionString": "",
    "MaxRetryCount": 3,
    "CommandTimeoutSeconds": 30
  }
}

Injecting Options

csharp
// IOptions<T> — singleton, read once at startup, doesn't change
public class OrderService(IOptions<DatabaseOptions> options)
{
    private readonly DatabaseOptions _db = options.Value;
}

// IOptionsSnapshot<T> — scoped, re-reads per request (for reloadable config)
public class OrderService(IOptionsSnapshot<DatabaseOptions> options)
{
    private readonly DatabaseOptions _db = options.Value;
}

// IOptionsMonitor<T> — singleton, actively watches for changes
public class BackgroundWorker(IOptionsMonitor<WorkerOptions> options)
{
    public void DoWork()
    {
        var current = options.CurrentValue; // Always latest
    }
}

Custom Validation (Complex Rules)

csharp
builder.Services.AddOptions<JwtOptions>()
    .BindConfiguration("Jwt")
    .Validate(options =>
    {
        if (string.IsNullOrEmpty(options.Key) || options.Key.Length < 32)
            return false;
        if (options.ExpirationMinutes <= 0)
            return false;
        return true;
    }, "JWT key must be at least 32 characters and expiration must be positive")
    .ValidateOnStart();

Azure Key Vault (Production)

csharp
// Program.cs — add Key Vault as a configuration source
if (builder.Environment.IsProduction())
{
    var keyVaultUri = new Uri(builder.Configuration["KeyVault:Uri"]!);
    builder.Configuration.AddAzureKeyVault(keyVaultUri, new DefaultAzureCredential());
}

Configuration for Multiple Environments

csharp
// Named options — different config per named instance
builder.Services.AddOptions<SmtpOptions>("internal")
    .BindConfiguration("Smtp:Internal");
builder.Services.AddOptions<SmtpOptions>("customer")
    .BindConfiguration("Smtp:Customer");

// Usage
public class EmailService(IOptionsSnapshot<SmtpOptions> options)
{
    public async Task SendInternalEmail(string to, string body)
    {
        var smtp = options.Get("internal");
        // ...
    }
}

Anti-patterns

Don't Read IConfiguration Directly

csharp
// BAD — stringly-typed, no validation, hard to test
public class OrderService(IConfiguration config)
{
    public void Process()
    {
        var timeout = int.Parse(config["Database:CommandTimeout"]!);
    }
}

// GOOD — strongly-typed options
public class OrderService(IOptions<DatabaseOptions> options)
{
    public void Process()
    {
        var timeout = options.Value.CommandTimeoutSeconds;
    }
}

Don't Put Secrets in appsettings.json

json
// BAD — committed to source control
{
  "Jwt": { "Key": "super-secret-key" },
  "Database": { "ConnectionString": "Server=prod;Password=secret" }
}

// GOOD — appsettings.json has defaults/structure only
{
  "Jwt": { "Key": "", "Issuer": "myapp", "Audience": "myapp" },
  "Database": { "ConnectionString": "" }
}
// Secrets provided via user-secrets (dev) or env vars / Key Vault (prod)

Don't Skip Startup Validation

csharp
// BAD — misconfiguration discovered at runtime
builder.Services.Configure<JwtOptions>(builder.Configuration.GetSection("Jwt"));

// GOOD — fail fast at startup
builder.Services.AddOptions<JwtOptions>()
    .BindConfiguration("Jwt")
    .ValidateDataAnnotations()
    .ValidateOnStart();

Decision Guide

ScenarioRecommendation
Binding config to classOptions pattern with BindConfiguration
Simple, immutable configIOptions<T>
Config that changes per requestIOptionsSnapshot<T>
Background service watching configIOptionsMonitor<T>
Development secretsdotnet user-secrets
Production secretsAzure Key Vault or environment variables
Validating configValidateDataAnnotations() + ValidateOnStart()
Multiple configs of same typeNamed options with IOptionsSnapshot<T>.Get(name)

Related by task

from this repository

More skills

All skills
codewithmukesh
Community

avalonia

Avalonia UI 12 for cross-platform .NET desktop apps: compiled bindings (x:DataType, on by default in 12), StyledProperty/DirectProperty, custom and templated controls, ControlThemes, DataTemplates/ViewLocator, Generic Host + DI, StorageProvider/Clipboard, Native AOT/trimming, and packaging. Load when the user mentions "Avalonia", "AXAML", "x:DataType", "compiled binding", "StyledProperty", "TemplatedControl", "ViewLocator", or "cross-platform desktop".

1h installs
3
GitHub stars
804
Updated
Nov 4
codewithmukesh
Community

console-cli

Console apps and CLI tools on .NET 10: System.CommandLine 2.x (RootCommand, Option , SetAction, InvokeAsync), Generic Host + DI in console apps, exit codes, stdout/stderr discipline, Ctrl+C cancellation, interactive vs piped use, dotnet tool packaging, and dotnet run app.cs file-based apps. Load when the user mentions "console app", "CLI", "command line", "System.CommandLine", "dotnet tool", "exit code", "stdin", "args parsing", or "file-based app".

1h installs
3
GitHub stars
804
Updated
Nov 4
codewithmukesh
Community

desktop-mvvm

MVVM for .NET desktop apps (WPF, Avalonia, WinForms, MAUI) with CommunityToolkit.Mvvm 8.4+ source generators: [ObservableProperty] partial properties, [RelayCommand] async commands, Generic Host + DI, UI-thread dispatching, navigation, messaging, and testable view models. Load when the user mentions "MVVM", "ViewModel", "WPF", "desktop app", "ObservableProperty", "RelayCommand", "ICommand", "INotifyPropertyChanged", "Dispatcher", or "UI thread".

1h installs
3
GitHub stars
804
Updated
Nov 4
codewithmukesh
Community

native-aot

Native AOT, trimming, and single-file publishing for .NET 10: PublishAot, IsAotCompatible analyzers, source-generated JSON/regex/logging/config binding, fixing IL2xxx/IL3xxx trim and AOT warnings, per-RID publishing, and when NOT to use AOT. Load when the user mentions "Native AOT", "PublishAot", "trimming", "PublishTrimmed", "single-file", "IL2026", "IL3050", "trim warning", "startup time", "self-contained", or "JsonSerializerContext".

1h installs
3
GitHub stars
804
Updated
Nov 4