Validering af Options og navngivne Options
Validér options ved opstart med DataAnnotations eller FluentValidation, og brug navngivne options til flere instanser.
Validering af Options og navngivne Options er en gratis C# Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i C# Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C# Academy-kurset indeholder 4 lektioner i alt.
Hvorfor validere options?
Manglende eller forkert udformet konfiguration medfører køretidsfejl, som er svære at spore. Validering af options ved opstart omdanner skjulte konfigurationsfejl til tydelige, beskrivende undtagelser, før nogen anmodning behandles.
ValidateOnStart
ValidateOnStart() udløser validering med det samme, når applikationen starter, i stedet for først ved den første brug. Det betyder, at en fejlkonfigureret udrulning mislykkes med det samme frem for flere timer senere.
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 configValidering med DataAnnotations
Brug standardattributter fra System.ComponentModel.DataAnnotations på din options-klasse. De evalueres automatisk af 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();Brugerdefineret valideringsdelegat
Overbelastningen Validate(Func<T, bool>, string) tilføjer en lambda til regler, der ikke kan udtrykkes med attributter, f.eks. begrænsninger på tværs af egenskaber.
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 til komplekse regler
Ved kompleks logik med flere fejlmeddelelser skal du implementere IValidateOptions<T>. Den modtager options-instansen og returnerer et resultat med detaljerede fejlmeddelelser.
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>();Navngivne options — koncept
Navngivne options lader dig registrere flere konfigurationer af samme optionstype. Et almindeligt anvendelsestilfælde er flere udgående HTTP-klienter, hver med forskellige basis-URL'er og tidsgrænser.
// 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;
}Registrering af navngivne options
Angiv en navnestreng som det første argument til Configure<T>. Brug IOptionsMonitor<T>.Get(name) til at hente en bestemt instans.
// 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
}Validering af navngivne options
Valider navngivne options enkeltvis ved at kalde AddOptions<T>(name) for hver navngiven registrering.
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 startOptionsBuilder API
OptionsBuilder<T> (returneret af AddOptions<T>()) er den kædede API, der på enkel vis sammenkæder alle trin til registrering, binding og validering.
// 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 validationVirkeligt eksempel: Options til genforsøgspolitik
En komplet opsætning af options til genforsøg med validering på tværs af felter og navngivne politikker til forskellige tjenester.
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();
}Hurtigt tjek
Hvad er fordelen ved at kalde ValidateOnStart(), når du registrerer options?
Opsummering: Options-validering og navngivne options
Vigtigste pointer:
ValidateOnStart(): fejl ved opstart i stedet for ved første brug- DataAnnotations:
[Required],[Range]osv. +ValidateDataAnnotations() Validate(Func, message): indlejret lambda til regler på tværs af egenskaberIValidateOptions<T>: fuld programmatisk validering med flere fejl- Navngivne options:
Configure<T>(name, ...)+IOptionsMonitor<T>.Get(name) OptionsBuilder<T>: kædet API til alle registreringstrin
Lær C# med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 93
- Lektioner
- 346
Ofte stillede spørgsmål
Er lektionen “Validering af Options og navngivne Options” gratis?
Ja — hele teksten til “Validering af Options og navngivne Options” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af C# Academy-kurset, skal du opgradere til CoddyKit PRO. C# Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Validering af Options og navngivne Options”?
Validér options ved opstart med DataAnnotations eller FluentValidation, og brug navngivne options til flere instanser. Du øver dig i C# Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på C# Academy?
Der kræves ingen tidligere erfaring. C# Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.
Hvor lang tid tager lektionen “Validering af Options og navngivne Options”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne C# Academy-lektion?
Ja. Alle C# Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Konfigurationskilder og -udbydere
- Stærkt typede Options med IOptions
- Validering af Options og navngivne Options
- Håndtering af secrets