Description
Background and motivation
To configure IOptions<T>
for IServiceCollection
, the OptionsServiceCollectionExtensions
class provides the Configure
/ PostConfigure
/ ConfigureAll
/ PostConfigureAll
methods.
But, there is no validation API except for AddOptionsWithValidateOnStart
.
In particular, there is no function to configure validation for all TOptions
types regardless of the option name (such as ValidateAll
).
We can validate all TOptions
by writing as follows.
But this is not documented and is not intuitive.
services.AddSingleton<IValidateOptions<TOptions>>(
new ValidateOptions<TOptions>(
name: null,
validation: static options => /* validation logic */,
failureMessage: "validation failed"));
API Proposal
namespace Microsoft.Extensions.DependencyInjection;
public static class OptionsServiceCollectionExtensions
{
public static IServiceCollection Validate<TOptions>(this IServiceCollection services, Action<TOptions, ValidateOptionsResult> validation);
public static IServiceCollection Validate<TOptions>(this IServiceCollection services, string? name, Action<TOptions, ValidateOptionsResult> validation);
public static IServiceCollection ValidateAll<TOptions>(this IServiceCollection services, Action<TOptions, ValidateOptionsResult> validation);
}
API Usage
var services = new ServiceCollection();
services
.Configure<MyOptions>(static options => /* configuration */)
.Validate(static options =>
MyValidationLogic(options, out var messages)
? ValidateOptionsResult.Success
: ValidateOptionsResult.Fail(messages));
Alternative Designs
It is also possible to design the delegate to return a bool
type instead of a ValidateOptionResult
, and to take the error message in the case where its result is false as another argument (as in the constructor of the ValidateOptions<TOptions>
class).
public static IServiceCollection Validate<TOptions>(this IServiceCollection services, Action<TOptions, bool> validation, string failureMessage);
Another possibility is the method names ValidateOptions
and ValidateAllOptions
. This is because the name Validate
does not sufficiently express what is being validated for IServiceCollection
.
However, this problem also exists with the existing Configure
and PostConfigure
. Therefore, those APIs will also be renamed to ConfigureOptions
and PostConfigureOptions
, and the existing APIs will be marked as [Obsolete]
.
There is a proposal to use OptionsBuilder<TOptions>
to configure all options.
Currently, even if written as follows, only unnamed options can be configured, and it is not possible to configure both named and unnamed options with a single OptionsBuilder<TOptions>
.
services.AddOptions<MyOptions>(null).Configure(...).Validate(...);
Since we can't change the behavior of AddOptions<MyOptions>(null)
, we'll probably introduce a new method like the following.
public static class OptionsServiceCollectionExtensions
{
public static OptionsBuilder<TOptions> AddOptionsForAll<TOptions>(this IServiceCollection services);
}
Risks
No response