К основному содержанию
скилл CX Codex

microsoft-extensions-configuration · aaronontheweb — скилл для Claude Code: валидация

Скилл для Claude и других ИИ-редакторов: подсказывает, как привязывать конфигурацию из appsettings.json к типизированным классам и проверять её на старте приложения.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add Aaronontheweb/dotnet-skills --skill microsoft-extensions-configuration -a claude-code
Открыть на GitHub

Что делает microsoft-extensions-configuration

Скилл описывает паттерны Microsoft.Extensions.Options для .NET: привязку секций конфигурации к строго типизированным классам, валидацию через Data Annotations и IValidateOptions, а также выбор между IOptions<T>, IOptionsSnapshot<T> и IOptionsMonitor<T>. Пригодится, когда агент пишет код настройки сервисов и надо, чтобы он не разбрасывал строковые ключи по коду.

Внутри — разбор четырёх паттернов с примерами на C#: базовый биндинг, атрибуты валидации, кастомный валидатор с внедрением зависимостей и время жизни опций. Отдельно разобрано, почему без .ValidateOnStart() проверка срабатывает только при первом обращении к опциям, а не при запуске. Есть ссылка на advanced-patterns.md с именованными опциями и валидаторами, которым нужны свои зависимости.

Скилл не про установку пакетов и не про конкретную версию .NET. Он даёт агенту шаблоны кода, поэтому проверяйте, что предложенный вариант совпадает с вашей версией Microsoft.Extensions.Options. Порядок важен: Data Annotations выполняются первыми, затем IValidateOptions, а ошибки собираются вместе.

Какие задачи решает

  • привязать секцию appsettings.json к типизированному классу настроек
  • проверить конфигурацию на старте и упасть с понятной ошибкой
  • описать валидацию, зависящую от нескольких свойств сразу
  • выбрать между IOptions, IOptionsSnapshot и IOptionsMonitor
  • подписаться на изменение настроек в фоновом сервисе

Примеры запросов агенту

  • Сделай класс SmtpSettings и привяжи его к секции Smtp из appsettings.json
  • Добавь валидатор IValidateOptions для настроек и включи ValidateOnStart
  • Мне нужны настройки, которые перечитываются на лету — что взять, IOptionsSnapshot или IOptionsMonitor?

Как установить microsoft-extensions-configuration

1Через Skills CLI (Vercel)

npx skills add Aaronontheweb/dotnet-skills --skill microsoft-extensions-configuration -a claude-code

2Вручную: положить файлы

~/.claude/skills/microsoft-extensions-configuration/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/microsoft-extensions-configuration/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Из того же набора32

api-design Скилл для проектирования публичных API по принципу «только расширять»: помогает не ломать совместимость при выпуске новых версий. CX Codex +1 660установок dotnet-project-structure Скилл подсказывает агенту, как разложить .NET-решение: .slnx, Directory.Build.props, центральные версии пакетов и SourceLink. CX Codex +1 658установок type-design-performance Скилл для проектирования типов .NET с оглядкой на производительность: запечатанные классы, readonly-структуры, отложенный перебор коллекций. CX Codex +1 655установок ilspy-decompile Декомпилирует сборки .NET через утилиту ilspycmd. Помогает изучать исходники пакетов NuGet и внутреннее устройство runtime-библиотек прямо в сессии агента. CX Codex +1 602установок serialization Помогает агенту выбрать формат сериализации для .NET: схему вместо рефлексии, System.Text.Json с генераторами для JSON. Пригодится при проектировании API, обмена сообщениями и хранения событий. CX Codex +1 569установок crap-analysis Скилл считает CRAP-оценки по покрытию и цикломатической сложности, чтобы найти в .NET-проекте код, который опасно менять. CX Codex +1 556установок dotnet-slopwatch Скилл отслеживает уловки нейросетей при правке кода C#: пропуск упавших тестов, скрытие предупреждений и пустые блоки catch. Он запускает утилиту slopwatch для защиты проекта от фиктивных правок. CX Codex +1 552установок testcontainers-integration-tests Скилл учит агента писать интеграционные тесты на .NET и xUnit с реальными базами и очередями в Docker вместо моков. Помогает проверять миграции, SQL-запросы и кэш без ложной уверенности. CX Codex +1 544установок

Другие версии microsoft-extensions-configuration

Похожие

microsoft-extensions-dependency-injection wshaddix Скилл для наведения порядка в регистрациях сервисов .NET: разбивает Program.cs на расширения и помогает выбрать время жизни сервиса. CX Codex +1 549установок microsoft-azure-webjobs-extensions-authentication-events-dotnet Microsoft Скилл для работы с кастомными событиями аутентификации Microsoft Entra ID в .NET: добавление claims в токены, сбор атрибутов, OTP. 1установок configuration codewithmukesh Настраивает конфигурацию .NET 10 через типизированные options, проверку и разделение секретов. Пригодится при работе с appsettings и переменными окружения. CX Codex +1 2 800установок validation-patterns wshaddix Скилл подсказывает агенту, как валидировать данные в ASP.NET Core: от атрибутов до FluentValidation и проверки конфигурации на старте. CX Codex +1 537установок python-configuration Seth Hobson Скилл выносит настройки Python в переменные окружения и проверяет их через типизированные параметры. Подходит для секретов и разных окружений. CX Codex 11 508установок collect-user-input dotnet Скилл для работы с формами в Blazor: EditForm, встроенные компоненты ввода, валидация и обработка отправки. Пригодится, когда нужно добавить форму, поиск или загрузку файлов. CX Codex +1 3 000установок

Рядом в теме «Бэкенд и API»

Всё по теме «Бэкенд и API» →

Вопросы о microsoft-extensions-configuration

Как установить microsoft-extensions-configuration в Claude?

Выполните npx skills add Aaronontheweb/dotnet-skills --skill microsoft-extensions-configuration -a claude-code. Скилл появится в ~/.claude/skills/microsoft-extensions-configuration/SKILL.md.

Что делает microsoft-extensions-configuration?

Даёт агенту паттерны Microsoft.Extensions.Options: биндинг конфигурации, валидацию через Data Annotations и IValidateOptions, проверку на старте и выбор времени жизни опций.

Чем IValidateOptions отличается от Data Annotations?

Атрибуты закрывают простые правила вроде обязательного поля или диапазона. IValidateOptions нужен для проверок, где сравниваются несколько свойств, есть условия или требуются свои зависимости. Оба механизма можно включить вместе.

Исходный текст

SKILL.md · MIT
---
name: microsoft-extensions-configuration
description: Microsoft.Extensions.Options patterns including IValidateOptions, strongly-typed settings, validation on startup, and the Options pattern for clean configuration management.
user-invocable: false
---

# Microsoft.Extensions Configuration Patterns

## When to Use This Skill

Use this skill when:
- Binding configuration from appsettings.json to strongly-typed classes
- Validating configuration at application startup (fail fast)
- Implementing complex validation logic for settings
- Designing configuration classes that are testable and maintainable
- Understanding IOptions<T>, IOptionsSnapshot<T>, and IOptionsMonitor<T>

## Reference Files

- [advanced-patterns.md](advanced-patterns.md): Validators with dependencies, named options, complete production example (AkkaSettings), and testing validators

## Why Configuration Validation Matters

**The Problem:** Applications often fail at runtime due to misconfiguration - missing connection strings, invalid URLs, out-of-range values. These failures happen deep in business logic, far from where configuration is loaded.

**The Solution:** Validate configuration at startup. If invalid, fail immediately with a clear error message.

```csharp
// BAD: Fails at runtime when someone tries to use the service
public class EmailService
{
    public EmailService(IOptions<SmtpSettings> options)
    {
        var settings = options.Value;
        // Throws NullReferenceException 10 minutes into production
        _client = new SmtpClient(settings.Host, settings.Port);
    }
}

// GOOD: Fails at startup with clear error
// "SmtpSettings validation failed: Host is required"
```

---

## Pattern 1: Basic Options Binding

### Define a Settings Class

```csharp
public class SmtpSettings
{
    public const string SectionName = "Smtp";

    public string Host { get; set; } = string.Empty;
    public int Port { get; set; } = 587;
    public string? Username { get; set; }
    public string? Password { get; set; }
    public bool UseSsl { get; set; } = true;
}
```

### Bind from Configuration

```csharp
builder.Services.AddOptions<SmtpSettings>()
    .BindConfiguration(SmtpSettings.SectionName);

// appsettings.json
{
  "Smtp": {
    "Host": "smtp.example.com",
    "Port": 587,
    "Username": "[email protected]",
    "Password": "secret",
    "UseSsl": true
  }
}
```

### Consume in Services

```csharp
public class EmailService
{
    private readonly SmtpSettings _settings;

    // IOptions<T> - singleton, read once at startup
    public EmailService(IOptions<SmtpSettings> options)
    {
        _settings = options.Value;
    }
}
```

---

## Pattern 2: Data Annotations Validation

For simple validation rules, use Data Annotations:

```csharp
using System.ComponentModel.DataAnnotations;

public class SmtpSettings
{
    public const string SectionName = "Smtp";

    [Required(ErrorMessage = "SMTP host is required")]
    public string Host { get; set; } = string.Empty;

    [Range(1, 65535, ErrorMessage = "Port must be between 1 and 65535")]
    public int Port { get; set; } = 587;

    [EmailAddress(ErrorMessage = "Username must be a valid email address")]
    public string? Username { get; set; }

    public string? Password { get; set; }
    public bool UseSsl { get; set; } = true;
}
```

### Enable Data Annotations Validation

```csharp
builder.Services.AddOptions<SmtpSettings>()
    .BindConfiguration(SmtpSettings.SectionName)
    .ValidateDataAnnotations()  // Enable attribute-based validation
    .ValidateOnStart();         // Validate immediately at startup
```

**Key Point:** `.ValidateOnStart()` is critical. Without it, validation only runs when the options are first accessed.

---

## Pattern 3: IValidateOptions<T> for Complex Validation

Data Annotations work for simple rules, but complex validation requires `IValidateOptions<T>`:

| Scenario | Data Annotations | IValidateOptions |
|----------|------------------|------------------|
| Required field | Yes | Yes |
| Range check | Yes | Yes |
| Cross-property validation | No | Yes |
| Conditional validation | No | Yes |
| External service checks | No | Yes |
| Dependency injection in validator | No | Yes |

### Implementing IValidateOptions

```csharp
using Microsoft.Extensions.Options;

public class SmtpSettingsValidator : IValidateOptions<SmtpSettings>
{
    public ValidateOptionsResult Validate(string? name, SmtpSettings options)
    {
        var failures = new List<string>();

        if (string.IsNullOrWhiteSpace(options.Host))
            failures.Add("Host is required");

        if (options.Port is < 1 or > 65535)
            failures.Add($"Port {options.Port} is invalid. Must be between 1 and 65535");

        // Cross-property validation
        if (!string.IsNullOrEmpty(options.Username) && string.IsNullOrEmpty(options.Password))
            failures.Add("Password is required when Username is specified");

        // Conditional validation
        if (options.UseSsl && options.Port == 25)
            failures.Add("Port 25 is typically not used with SSL. Consider port 465 or 587");

        return failures.Count > 0
            ? ValidateOptionsResult.Fail(failures)
            : ValidateOptionsResult.Success;
    }
}
```

### Register the Validator

```csharp
builder.Services.AddOptions<SmtpSettings>()
    .BindConfiguration(SmtpSettings.SectionName)
    .ValidateDataAnnotations()
    .ValidateOnStart();

builder.Services.AddSingleton<IValidateOptions<SmtpSettings>, SmtpSettingsValidator>();
```

**Order matters:** Data Annotations run first, then IValidateOptions validators. All failures are collected together.

See [advanced-patterns.md](advanced-patterns.md) for validators with dependencies, named options, and a complete production example.

---

## Pattern 4: Options Lifetime

| Interface | Lifetime | Reloads on Change | Use Case |
|-----------|----------|-------------------|----------|
| `IOptions<T>` | Singleton | No | Static config, read once |
| `IOptionsSnapshot<T>` | Scoped | Yes (per request) | Web apps needing fresh config |
| `IOptionsMonitor<T>` | Singleton | Yes (with callback) | Background services, real-time updates |

### IOptionsMonitor for Background Services

```csharp
public class BackgroundWorker : BackgroundService
{
    private readonly IOptionsMonitor<WorkerSettings> _optionsMonitor;
    private WorkerSettings _currentSettings;

    public BackgroundWorker(IOptionsMonitor<WorkerSettings> optionsMonitor)
    {
        _optionsMonitor = optionsMonitor;
        _currentSettings = optionsMonitor.CurrentValue;

        _optionsMonitor.OnChange(settings =>
        {
            _currentSettings = settings;
        });
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            await DoWorkAsync();
            await Task.Delay(_currentSettings.PollingInterval, stoppingToken);
        }
    }
}
```

---

## Pattern 5: Post-Configuration

Modify options after binding but before validation:

```csharp
builder.Services.AddOptions<ApiSettings>()
    .BindConfiguration("Api")
    .PostConfigure(options =>
    {
        if (!string.IsNullOrEmpty(options.BaseUrl) && !options.BaseUrl.EndsWith('/'))
            options.BaseUrl += '/';

        options.Timeout ??= TimeSpan.FromSeconds(30);
    })
    .ValidateDataAnnotations()
    .ValidateOnStart();
```

---

## Anti-Patterns to Avoid

### 1. Manual Configuration Access

```csharp
// BAD: Bypasses validation, hard to test
public class MyService
{
    public MyService(IConfiguration configuration)
    {
        var host = configuration["Smtp:Host"]; // No validation!
    }
}

// GOOD: Strongly-typed, validated
public class MyService
{
    public MyService(IOptions<SmtpSettings> options)
    {
        var host = options.Value.Host; // Validated at startup
    }
}
```

### 2. Validation in Constructor

```csharp
// BAD: Validation happens at runtime, not startup
public class MyService
{
    public MyService(IOptions<Settings> options)
    {
        if (string.IsNullOrEmpty(options.Value.Required))
            throw new ArgumentException("Required is missing"); // Too late!
    }
}

// GOOD: Validation at startup via IValidateOptions + ValidateOnStart()
```

### 3. Forgetting ValidateOnStart

```csharp
// BAD: Validation only runs when first accessed
builder.Services.AddOptions<Settings>()
    .ValidateDataAnnotations(); // Missing ValidateOnStart!

// GOOD: Fails immediately if invalid
builder.Services.AddOptions<Settings>()
    .ValidateDataAnnotations()
    .ValidateOnStart();
```

### 4. Throwing in IValidateOptions

```csharp
// BAD: Throws exception, breaks validation chain
public ValidateOptionsResult Validate(string? name, Settings options)
{
    if (options.Value < 0)
        throw new ArgumentException("Value cannot be negative"); // Wrong!
    return ValidateOptionsResult.Success;
}

// GOOD: Return failure result
public ValidateOptionsResult Validate(string? name, Settings options)
{
    if (options.Value < 0)
        return ValidateOptionsResult.Fail("Value cannot be negative");
    return ValidateOptionsResult.Success;
}
```

---

## Summary

| Principle | Implementation |
|-----------|----------------|
| Fail fast | `.ValidateOnStart()` |
| Strongly-typed | Bind to POCO classes |
| Simple validation | Data Annotations |
| Complex validation | `IValidateOptions<T>` |
| Cross-property rules | `IValidateOptions<T>` |
| Environment-aware | Inject `IHostEnvironment` |
| Testable | Validators are plain classes |

© Aaronontheweb · MIT · Aaronontheweb/dotnet-skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой