runtime: Developers can get immediate feedback on validation problems
Updated by @maryamariyan:
Goal
When an application starts, we want to get immediate feedback on validation problems. e.g. we would like to get exceptions thrown on app startup rather than later.
Benefits of eager validation:
- Enabling this feature forces the program to crash fast when an invalid configuration is passed, as opposed to the default lazy validation only when
IOptions<T>
is requested
API Proposal
ValidateOnStart
feature is implemented as extension to OptionsBuilder<TOptions>
To allow for eager validation, an API suggestion is to add an extension method on OptionsBuilder, (not IHost).
Usage:
services.AddOptions<MyOptions>()
.ValidateDataAnnotations()
.ValidateOnStart(); // Support eager validation
APIs:
According to usage, we’d need the APIs below:
namespace Microsoft.Extensions.DependencyInjection
{
public static class OptionsBuilderExtensions
{
public static OptionsBuilder<TOptions> ValidateOnStart<TOptions>(this OptionsBuilder<TOptions> optionsBuilder) where TOptions : class;
}
}
Focus of this issue:
The focus here is on eager validation at application startup, and these APIs don’t trigger for IOptionsSnapshot and IOptionsMonitor, where values may get recomputed on every request or upon configuration reload after the startup has completed.
- It would support named options too.
IOptions<TOptions>
:
- Reads configuration data only after the app has started.
- Does not support named options
IOptionsSnapshot<TOptions>
:
May be recomputed on every request, and supports named options
IOptionsMonitor<TOptions>
:
Is registered as a singleton, supports named options, change notifications, configuration reloads, and can be injected to any service lifetime.
Original Description (click to view)
AB#1244419 From exp review with @ajcvickers @DamianEdwards @Eilon @davidfowl
We should support some mechanism for eager (fail fast on startup) validation of options.
Needs to also work for generic host as well as webhost, must be configurable on a per options instance, since this will never work for request based options.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 46
- Comments: 27 (18 by maintainers)
Thank you for all the great ideas in this thread. I wanted to retain the Validate and ValidateDataAnnotations provided by OptionsBuilder but enable eager validation, the patterns above led me to:
Usage:
Classes:
I prefer ValidateOnStartup, though people may think it has something to do with the Startup class. What about
ValidateOnStart
?The empty error message of
OptionsValidationException
is utterly unhelpful - at least an error message containing the number of errors and the first error would be much more helpful. As the current implementation stands unless the exception is specifically caught and the containing errors manually logged there is no way to know what the error is except that it is somewhere in the configuration. Even having the first error message will be extremely helpful as even if there are more than one errors they can be addressed one by one.A possible implementation:
I wrote a post about my approach here: https://andrewlock.net/adding-validation-to-strongly-typed-configuration-objects-in-asp-net-core/, and I have NuGet package to provide the funcitonality: https://github.com/andrewlock/NetEscapades.Configuration/blob/master/src/NetEscapades.Configuration.Validation
Essentially, I implement a simple interface in my options objects (
IValidatable
), and register it with the DI container. You can perform the validation any way you like (DataAnnotation
s, Fluent validation etc).Then I have a
StartupFilter
that just callsValidate
on all the settings:Any exceptions will happen on app startup. There’s a few caveats to this approach:
IStartupFilter
is HTTP/middleware specific AFAIK, not generic hostIOptionsMonitor
approach.Just be aware that using
IStartupFilter
won’t work for non-host apps, consider command line application, Azure Function or AWS Lambda. (I would expect something more handy than manually resolving options from service provider)Another thing to consider: how should be “reloadOnChange” handled? Last thing I want is to throw at runtime. With current instrumentation of
IOptionsMonitor<T>.OnChange
I get last valid options (good), in other hand, I’m not getting notification about changed invalid options (not so good).I have created a small class (based on the idea by @andrewlock of using an
IStartupFilter
) that “extends” theOptionsConfigurationServiceCollectionExtensions.Configure
method by adding validation and also supports eager validation at startup.Usage:
Class:
@maryamariyan can you please ensure User stories have a title in the form “XXX can YY” indicating what user experience changes. Take a look at other titles: https://themesof.net/?q=is:open kinds:ub team:Libraries Same for #44517.
Thanks @andrewlock I’m guessing we will end up with something similar just in a more generic host friendly way, that probably uses options itself to configure what option instances to validate at startup.