Using built-in methods to configure and validate option
An important part of any asp.net web application is how we handle our project settings, and from my point of view, a very strong emphasis should be set on how to validate our settings.
Think about what happens when you miss setting a proper int configuration value, would its default be acceptable?
You can find a link to the demo using the following link: https://github.com/ramihamati/webapidemos/tree/main/WebApi.DemoOptions
You can find this article also on my medium page: https://medium.com/@hamatirami/how-to-configure-options-in-asp-net-4869f2efd01f
Following article sections:
Configureto register an option
- What’s behind the
IConfigureOptionsto configure an option
IValidateOptionsto validate the option values
- Validate with annotations
Using Configure to register an option
Adding a configuration model in Asp.NET can be achieved as simply as creating a configuration model and then using the
That’s great, now we can simply access our options by demanding the
IOptions<OptionMongoDb> from our dependency mechanism:
What's behind the Configure method
In the previous section, we added an option using the
Configure method, which registers an option service for our configuration. But what’s behind that method?
Decompiling that code we can see that this method registers the options services using
AddOptions and then it adds a service for our option as the interface
Now this tells me that I don’t have to call myself the method
services.AddOptions() because it’s being made automatically, and no need to worry about these services being added multiple times because internally they use
TryAdd extension methods.
Using IConfigureOptions to configure an option
In the previous section we saw that internally when configuring an option, the framework registers the service
IConfigureOption<TOption> which is used to configure the option model. The Asp.NET framework uses a service that binds the option model to the configuration section.
We can have our custom implementation of this configuration service.
Let’s define a new option model and implement the configuration class:
We should make sure that we are registering the options services by calling
services.AddOptions() then we can register our new service:
Using IValidateOptions to validate the option values
We have multiple methods to validate our configuration model properties. In the previous section, I added some basic property validations in the
IConfigureOption<> service, but we also have a handy service called
IValidateOption<> service which can also be used for the same purpose.
With this method the validation is performed when a property on that object is called (not when the object is configured)
Validate with annotations
A nice feature is to use annotations to validate our options model.
We have to use the
AddOptions<> method which uses an
OptionBuilder internally that has more neat functionalities, like validating data annotations or validating at startup. We can also register some predicate validations (not as cool as using
Let’s register our new option model with the validations in place
Now we can run the validations at startup by registering the options like:
Annoyingly I can’t see a way to bind the
IValidateOptions to the
OptionBuilder or making the
IValidateOptions to run at starttime instead of runtime like the
Also annoying is the fact that we have too many ways of describing the same thing. Wouldn’t it be nice to just have one way of registering, configuring and validating? Instead of focusing on our business logic, we have to struggle understanding all these different ways and behaviours.