0Pricing
C# Academy · Lektion

Optionsvalidierung und benannte Optionen

Validieren Sie Optionen beim Start mit DataAnnotations oder FluentValidation und verwenden Sie benannte Optionen für mehrere Instanzen.

Optionsvalidierung und benannte Optionen ist eine kostenlose C# Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des C# Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der C# Academy-Kurs umfasst insgesamt 4 Lektionen.

Warum Optionen validieren?

Fehlende oder fehlerhafte Konfiguration verursacht Laufzeitfehler, die sich nur schwer zurückverfolgen lassen. Wenn Sie Optionen beim Start validieren, werden unauffällige Konfigurationsfehler in aussagekräftige Ausnahmen umgewandelt, bevor irgendeine Anfrage verarbeitet wird.

ValidateOnStart

ValidateOnStart() startet die Validierung unmittelbar beim Start der Anwendung und nicht erst verzögert bei der ersten Verwendung. Eine falsch konfigurierte Bereitstellung schlägt dadurch sofort statt erst Stunden später fehl.

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

Validierung mit DataAnnotations

Verwenden Sie standardmäßige Attribute aus System.ComponentModel.DataAnnotations für Ihre Options-Klasse. Sie werden von ValidateDataAnnotations() automatisch ausgewertet.

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();

Benutzerdefinierter Validierungsdelegat

Die Überladung Validate(Func<T, bool>, string) fügt einen Lambda-Ausdruck für Regeln hinzu, die sich nicht mit Attributen ausdrücken lassen, etwa Einschränkungen zwischen mehreren Eigenschaften.

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 für komplexe Regeln

Für komplexe Logik mit mehreren Fehlermeldungen implementieren Sie IValidateOptions<T>. Die Implementierung erhält die Optionsinstanz und gibt ein Ergebnis mit detaillierten Fehlermeldungen zurück.

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>();

Benannte Optionen – Konzept

Mit benannten Optionen können Sie mehrere Konfigurationen desselben Optionstyps registrieren. Ein typischer Anwendungsfall sind mehrere ausgehende HTTP-Clients mit jeweils unterschiedlichen Basis-URLs und Timeouts.

// 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;
}

Benannte Optionen registrieren

Übergeben Sie eine Namenszeichenfolge als erstes Argument an Configure<T>. Verwenden Sie IOptionsMonitor<T>.Get(name), um eine bestimmte Instanz abzurufen.

// 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
}

Benannte Optionen validieren

Validieren Sie benannte Optionen einzeln, indem Sie für jede benannte Registrierung AddOptions<T>(name) aufrufen.

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

OptionsBuilder-API

OptionsBuilder<T> (wird von AddOptions<T>() zurückgegeben) ist die Fluent-API, mit der sich alle Schritte für Registrierung, Bindung und Validierung übersichtlich miteinander verknüpfen lassen.

// 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

Praxisbeispiel: Optionen für Wiederholungsrichtlinien

Eine vollständige Konfiguration für Wiederholungsoptionen mit Validierung von Eigenschaften über mehrere Felder hinweg und benannten Richtlinien für verschiedene Dienste.

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();
}

Schnelltest

Welchen Vorteil bietet der Aufruf von ValidateOnStart() bei der Registrierung von Optionen?

Zusammenfassung: Options-Validierung und benannte Optionen

Wichtige Erkenntnisse:

  • ValidateOnStart(): Fehler beim Start statt bei der ersten Verwendung
  • DataAnnotations: [Required], [Range] usw. + ValidateDataAnnotations()
  • Validate(Func, message): Inline-Lambda für Regeln zwischen mehreren Eigenschaften
  • IValidateOptions<T>: vollständige programmgesteuerte Validierung mit mehreren Fehlern
  • Benannte Optionen: Configure<T>(name, ...) + IOptionsMonitor<T>.Get(name)
  • OptionsBuilder<T>: Fluent-API zum Verknüpfen aller Registrierungsschritte

Häufig gestellte Fragen

Ist die Lektion „Optionsvalidierung und benannte Optionen“ kostenlos?

Ja — der vollständige Text von „Optionsvalidierung und benannte Optionen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des C# Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der C# Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Optionsvalidierung und benannte Optionen“?

Validieren Sie Optionen beim Start mit DataAnnotations oder FluentValidation und verwenden Sie benannte Optionen für mehrere Instanzen. Du übst C# Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um C# Academy zu starten?

Keine Vorkenntnisse erforderlich. C# Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Optionsvalidierung und benannte Optionen“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser C# Academy-Lektion Code schreiben und ausführen?

Ja. Jede C# Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Konfigurationsquellen und -anbieter
  2. Typsichere Optionen mit IOptions
  3. Optionsvalidierung und benannte Optionen
  4. Geheimnisverwaltung
← Zurück zu C# Academy