0Pricing
C# Academy · Leçon

Validation des options et options nommées

Validez les options au démarrage avec DataAnnotations ou FluentValidation et utilisez des options nommées pour plusieurs instances.

Validation des options et options nommées est une leçon C# Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C# Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C# Academy comprend 4 leçons au total.

Pourquoi valider les options ?

Une configuration manquante ou malformée provoque des erreurs à l’exécution difficiles à retracer. Valider les options au démarrage transforme les problèmes de configuration silencieux en exceptions explicites et descriptives, avant qu’une quelconque requête soit traitée.

ValidateOnStart

ValidateOnStart() déclenche immédiatement la validation au démarrage de l’application, plutôt que de l’effectuer de manière différée lors de la première utilisation. Ainsi, un déploiement mal configuré échoue instantanément au lieu d’échouer plusieurs heures plus tard.

builder.Services
    .AddOptions<DatabaseOptions>()
    .BindConfiguration("Database")
    .ValidateDataAnnotations()
    .ValidateOnStart(); // throw OptionsValidationException on startup

// Without ValidateOnStart:
// - Validation only runs on first IOptions<T>.Value access
// - A rarely-used service could run for hours before failing

// With ValidateOnStart:
// - App fails at Host.Run() if config is invalid
// - Health checks and probes never report healthy for bad config

Validation avec DataAnnotations

Utilisez les attributs standard System.ComponentModel.DataAnnotations sur votre classe d’options. Ils sont évalués automatiquement par ValidateDataAnnotations().

using System.ComponentModel.DataAnnotations;

public class EmailOptions
{
    [Required(ErrorMessage = "SMTP host is required")]
    [MinLength(3)]
    public string SmtpHost { get; set; } = string.Empty;

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

    [Required]
    [EmailAddress(ErrorMessage = "Invalid sender address")]
    public string SenderAddress { get; set; } = string.Empty;

    [Range(1, 30)]
    public int TimeoutSeconds { get; set; } = 10;
}

builder.Services
    .AddOptions<EmailOptions>()
    .BindConfiguration("Email")
    .ValidateDataAnnotations()
    .ValidateOnStart();

Délégué de validation personnalisé

La surcharge Validate(Func<T, bool>, string) ajoute une fonction lambda pour les règles qui ne peuvent pas être exprimées avec des attributs, comme les contraintes entre propriétés.

builder.Services
    .AddOptions<ConnectionPoolOptions>()
    .BindConfiguration("ConnectionPool")
    .ValidateDataAnnotations()
    .Validate(
        opts => opts.MaxSize >= opts.MinSize,
        "MaxSize must be greater than or equal to MinSize")
    .Validate(
        opts => opts.ConnectionTimeoutMs > 0,
        "ConnectionTimeoutMs must be positive")
    .ValidateOnStart();

public class ConnectionPoolOptions
{
    [Range(1, 100)] public int MinSize { get; set; } = 2;
    [Range(1, 500)] public int MaxSize { get; set; } = 20;
    public int ConnectionTimeoutMs { get; set; } = 5000;
}

IValidateOptions pour les règles complexes

Pour une logique complexe avec plusieurs messages d’erreur, implémentez IValidateOptions<T>. Il reçoit l’instance des options et renvoie un résultat contenant des messages d’échec détaillés.

public class PaymentOptionsValidator : IValidateOptions<PaymentOptions>
{
    public ValidateOptionsResult Validate(string? name, PaymentOptions opts)
    {
        var failures = new List<string>();

        if (opts.Provider == "Stripe" && string.IsNullOrWhiteSpace(opts.StripeSecretKey))
            failures.Add("StripeSecretKey is required when Provider is Stripe");

        if (opts.Provider == "PayPal" && string.IsNullOrWhiteSpace(opts.PayPalClientId))
            failures.Add("PayPalClientId is required when Provider is PayPal");

        if (opts.RetryCount < 0 || opts.RetryCount > 5)
            failures.Add("RetryCount must be between 0 and 5");

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

builder.Services.AddSingleton<IValidateOptions<PaymentOptions>, PaymentOptionsValidator>();

Options nommées — concept

Les options nommées vous permettent d’enregistrer plusieurs configurations du même type d’options. Un cas d’utilisation courant consiste à définir plusieurs clients HTTP sortants, chacun avec des URL de base et des délais d’attente différents.

// appsettings.json:
{
  "HttpClients": {
    "Orders": {
      "BaseUrl": "https://orders-service",
      "TimeoutSeconds": 30
    },
    "Inventory": {
      "BaseUrl": "https://inventory-service",
      "TimeoutSeconds": 10
    }
  }
}

public class HttpClientOptions
{
    public string BaseUrl { get; set; } = string.Empty;
    public int TimeoutSeconds { get; set; } = 30;
}

Enregistrer des options nommées

Passez une chaîne de caractères représentant le nom comme premier argument à Configure<T>. Utilisez IOptionsMonitor<T>.Get(name) pour résoudre une instance précise.

// Register:
builder.Services.Configure<HttpClientOptions>("Orders",
    builder.Configuration.GetSection("HttpClients:Orders"));
builder.Services.Configure<HttpClientOptions>("Inventory",
    builder.Configuration.GetSection("HttpClients:Inventory"));

// Consume:
public class ApiGateway
{
    private readonly HttpClientOptions _orders;
    private readonly HttpClientOptions _inventory;

    public ApiGateway(IOptionsMonitor<HttpClientOptions> monitor)
    {
        _orders    = monitor.Get("Orders");
        _inventory = monitor.Get("Inventory");
    }

    // IOptions<T>.Value always returns the unnamed (default) instance
    // IOptionsMonitor<T>.Get(name) returns the named instance
}

Options nommées avec validation

Validez les options nommées individuellement en appelant AddOptions<T>(name) pour chaque enregistrement nommé.

foreach (var clientName in new[] { "Orders", "Inventory", "Auth" })
{
    builder.Services
        .AddOptions<HttpClientOptions>(clientName)
        .BindConfiguration($"HttpClients:{clientName}")
        .ValidateDataAnnotations()
        .Validate(
            opts => Uri.IsWellFormedUriString(opts.BaseUrl, UriKind.Absolute),
            $"HttpClients:{clientName}:BaseUrl must be a valid absolute URI")
        .ValidateOnStart();
}

// If any named instance fails, the app refuses to start

API OptionsBuilder

OptionsBuilder<T> (renvoyé par AddOptions<T>()) est l’API fluide qui enchaîne proprement toutes les étapes d’enregistrement, de liaison et de validation.

// Full OptionsBuilder chain:
builder.Services
    .AddOptions<DatabaseOptions>()        // create builder
    .BindConfiguration("Database")         // bind JSON section
    .Configure(opts =>                     // manual override
    {
        if (builder.Environment.IsDevelopment())
            opts.EnableDetailedErrors = true;
    })
    .PostConfigure(opts =>                 // runs after all Configure
    {
        opts.ConnectionString ??= "default-fallback";
    })
    .ValidateDataAnnotations()             // attribute rules
    .Validate(o => o.MaxPoolSize > 0,
              "MaxPoolSize must be positive")
    .ValidateOnStart();                    // eager validation

En pratique : options de stratégie de nouvelle tentative

Une configuration complète des options de nouvelle tentative, avec validation entre les champs et stratégies nommées pour différents services.

public class RetryOptions
{
    [Range(0, 10)] public int MaxAttempts { get; set; } = 3;
    [Range(100, 60000)] public int BaseDelayMs { get; set; } = 500;
    public bool UseExponentialBackoff { get; set; } = true;
    [Range(1, 120000)] public int MaxDelayMs { get; set; } = 30000;
}

foreach (var policy in new[] { "Database", "HttpClient", "MessageBus" })
{
    builder.Services
        .AddOptions<RetryOptions>(policy)
        .BindConfiguration($"RetryPolicies:{policy}")
        .Validate(o => !o.UseExponentialBackoff || o.MaxDelayMs > o.BaseDelayMs,
                  "MaxDelayMs must exceed BaseDelayMs when using exponential backoff")
        .ValidateOnStart();
}

Vérification rapide

Quel est l’avantage d’appeler ValidateOnStart() lors de l’enregistrement des options ?

Récapitulatif : validation des options et options nommées

Points clés à retenir :

  • ValidateOnStart() : échouer au démarrage plutôt que lors de la première utilisation
  • DataAnnotations : [Required], [Range], etc. + ValidateDataAnnotations()
  • Validate(Func, message) : fonction lambda intégrée pour les règles entre propriétés
  • IValidateOptions<T> : validation programmatique complète avec plusieurs erreurs
  • Options nommées : Configure<T>(name, ...) + IOptionsMonitor<T>.Get(name)
  • OptionsBuilder<T> : API fluide permettant d’enchaîner toutes les étapes d’enregistrement

Questions Fréquemment Posées

La leçon « Validation des options et options nommées » est-elle gratuite ?

Oui — le texte complet de « Validation des options et options nommées » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C# Academy, passe à CoddyKit PRO. Le cours C# Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Validation des options et options nommées » ?

Validez les options au démarrage avec DataAnnotations ou FluentValidation et utilisez des options nommées pour plusieurs instances. Tu pratiques C# Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer C# Academy ?

Aucune expérience préalable n'est requise. C# Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « Validation des options et options nommées » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon C# Academy ?

Oui. Chaque leçon C# Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Sources et fournisseurs de configuration
  2. Options fortement typées avec IOptions
  3. Validation des options et options nommées
  4. Gestion des secrets
← Retour à C# Academy