Nóta
Aðgangur að þessari síðu krefst heimildar. Þú getur prófað aðskrá þig inn eða breyta skráasöfnum.
Aðgangur að þessari síðu krefst heimildar. Þú getur prófað að breyta skráasöfnum.
Starting in .NET 11 RC 1, synchronous access to an options type that uses only asynchronous validators fails fast. Instead of returning an options instance without asynchronous validation, the synchronous creation path throws an OptionsValidationException.
Version introduced
.NET 11 RC 1
Previous behavior
Previously, in .NET 11 Preview 6 and Preview 7, IAsyncValidateOptions<TOptions> was independent from IValidateOptions<TOptions>. Asynchronous validators ran only through the asynchronous startup-validation path.
When you accessed an async-validated options type through a synchronous creation path, such as IOptions<TOptions>.Value, CurrentValue, Get, IOptionsSnapshot<TOptions>.Value, Get, or Create, the asynchronous validator didn't run. The synchronous path returned an unvalidated options instance.
Types that implemented IAsyncValidateOptions<TOptions> directly only needed to implement ValidateAsync.
New behavior
Starting in .NET 11 RC 1, IAsyncValidateOptions<TOptions> derives from IValidateOptions<TOptions>, and the interface is no longer contravariant. Asynchronous validators participate in the same validator collection as synchronous validators.
When you access an options type with only asynchronous validators through a synchronous creation path, the inherited Validate method returns a failed ValidateOptionsResult. Create then throws an OptionsValidationException. The exception message directs you to call ValidateOnStart and complete startup before you synchronously access the options.
Custom types that implement IAsyncValidateOptions<TOptions> directly must now also implement the inherited Validate method.
Type of breaking change
This change is a behavioral change and can affect source compatibility. In a narrow scenario where a preview binary directly implements IAsyncValidateOptions<TOptions> without recompilation, the change can also affect binary compatibility.
Reason for change
Asynchronous options validation was introduced in .NET 11 Preview 6 as a startup-only validation path. Later design work for post-startup validation exposed a correctness gap: Options also have synchronous creation and access paths. A validator that implemented only the async interface couldn't run through those synchronous paths, so invalid options could be returned and cached before asynchronous validation ran.
To close that gap before the API reaches a stable release, IAsyncValidateOptions<TOptions> now derives from IValidateOptions<TOptions>. The unified contract keeps one validator collection, preserves registration order, and makes unsupported synchronous access fail with an actionable exception. For more information, see dotnet/runtime#131197 and the approved API proposal.
Recommended action
For options that use only asynchronous validators, call ValidateOnStart and complete host startup before you access the options synchronously:
services.AddOptions<MyOptions>()
.Configure(o => o.Value = 42)
.ValidateAsync(o => Task.FromResult(o.Value > 0), "Value must be positive.")
.ValidateOnStart();
await host.StartAsync();
Avoid synchronous access to options with only asynchronous validators before startup completes. This guidance applies to IOptions<TOptions>.Value, IOptionsMonitor<TOptions>.CurrentValue, IOptionsMonitor<TOptions>.Get, IOptionsSnapshot<TOptions>.Value, IOptionsSnapshot<TOptions>.Get, and IOptionsFactory<TOptions>.Create.
Some paths remain synchronous even after you use ValidateOnStart. Startup validation doesn't seed IOptionsSnapshot<TOptions> values for later scopes, and IOptionsMonitor<TOptions> recreates options synchronously after a configuration change. If you need those paths to validate successfully, keep at least one synchronous validator.
If you implement IAsyncValidateOptions<TOptions> directly, add the inherited Validate(string? name, TOptions options) method and recompile against .NET 11. Return ValidateOptionsResult.Skip when the validator doesn't apply, or return ValidateOptionsResult.Fail when synchronous validation isn't supported.
If your code relied on the removed in TOptions contravariance, update the affected assignments, casts, or registrations.
You can't control this behavior with an AppContext switch or configuration setting.
Affected APIs
- IAsyncValidateOptions<TOptions>
- IValidateOptions<TOptions>
- AsyncValidateOptions<TOptions>
- AsyncValidateOptions<TOptions,TDep>
- AsyncValidateOptions<TOptions,TDep1,TDep2>
- AsyncValidateOptions<TOptions,TDep1,TDep2,TDep3>
- AsyncValidateOptions<TOptions,TDep1,TDep2,TDep3,TDep4>
- AsyncValidateOptions<TOptions,TDep1,TDep2,TDep3,TDep4,TDep5>
- Value
- CurrentValue
- Get
- Get
- Create
- Create
ValidateAsyncextension methods onOptionsBuilder<TOptions>.