[Quick Tip] Improving developer experience with Options Pattern validation on start.
Tags: dotnet
Published: 2021-05-27 18:53:49

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()`:

```c#
public static class ServiceCollectionExtensions
{
    public static OptionsBuilder<ApplicationOptions> ConfigureApplicationOptions(
        this IServiceCollection services, IConfigurationSection section)
        => services
            .AddOptions<ApplicationOptions>()
            .Bind(section)
            .ValidateDataAnnotations()
            .ValidateOnStart();
}
```

And the usage in StartUp:

```c#
services.ConfigureApplicationOptions(
    _configuration.GetSection(nameof(ApplicationOptions)));
```

`ApplicationOptions` defining property as **Required** and **URL**:

```c#
public class ApplicationOptions
{
    [Required, Url]
    public string HttpClientAddress { get; init; }
}
```

`AppSettings` setting the address wrongly on purpose:

```json
{
  "ApplicationOptions": {
    "HttpClientAddress" : "localhost"
    }
}
```

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

```log
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.'.
```

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:

```c#
=> 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();
```


### Conclusion

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