DEV Community

Cover image for [Quick Tip] Improving developer experience with Options Pattern validation on start.
Antonio Falcão Jr.
Antonio Falcão Jr.

Posted on

[Quick Tip] Improving developer experience with Options Pattern validation on start.

When we're new or have less contact with some project is hard to understand all configuration possibilities.

Option pattern is the most appropriate way to inject environment settings options into the application. isolating the options by scenario is adhering to important software engineering principles, such as Principle of Interface Segregation (ISP) and Separation of Concerns.

Validate the options is a good way to indicate what or how the definitions are out of the expectations, But until .NET 5 the interruption provided from validation just was thrown in run time.

From .NET 6 it is possible to enforce options validation check on start rather than in runtime, with the ValidatiOnStart() extension method from OptionsBuilder<TOptions>.

Below a simple example using ValidateDataAnnotations() and ValidateOnStart():

public static class ServiceCollectionExtensions
{
    public static OptionsBuilder<ApplicationOptions> ConfigureApplicationOptions(
        this IServiceCollection services, IConfigurationSection section)
        => services
            .AddOptions<ApplicationOptions>()
            .Bind(section)
            .ValidateDataAnnotations()
            .ValidateOnStart();
}
Enter fullscreen mode Exit fullscreen mode

And the usage in StartUp:

services.ConfigureApplicationOptions(
    _configuration.GetSection(nameof(ApplicationOptions)));
Enter fullscreen mode Exit fullscreen mode

ApplicationOptions defining property as Required and URL:

public class ApplicationOptions
{
    [Required, Url]
    public string HttpClientAddress { get; init; }
}
Enter fullscreen mode Exit fullscreen mode

AppSettings setting the address wrongly on purpose:

{
  "ApplicationOptions": {
    "HttpClientAddress" : "localhost"
    }
}
Enter fullscreen mode Exit fullscreen mode

And then, when running the application, the interruption throws the error:

Microsoft.Extensions.Options.OptionsValidationException:
DataAnnotation validation failed for members: 'HttpClientAddress'
with the error: 'The HttpClientAddress field is not a valid
fully-qualified http, https, or ftp URL.'.
Enter fullscreen mode Exit fullscreen mode

As we can see, the error is pretty clear and indicates what way we can take to solve the problem.

Another validation approache

Data Annotations is not the only way to validate the options. The Validate() method provides a delegate Func<TOptions, bool> that allows any kind of validation strategy.

This sample uses the library Fluent Validation with InlineValidator<T> just to exemplify:

=> services
    .AddOptions<ApplicationOptions>()
    .Bind(section)
    .Validate(options =>
        {
            var validator = new InlineValidator<ApplicationOptions>();

            validator
                .RuleFor(applicationOptions => applicationOptions.HttpClientAddress)
                .NotNull()
                .NotEmpty()
                .WithMessage("HttpClientAddress must be informed");

            return validator
                .Validate(options, strategy => strategy.ThrowOnFailures())
                .IsValid;
        })
    .ValidateOnStart();
Enter fullscreen mode Exit fullscreen mode

Conclusion

This tool as simple as powerful to help to have a better development environment.

Top comments (1)

Collapse
 
renatorcribeiro profile image
Renato Ribeiro

Parabéns pelo post, bem explicado e objetivo.