I like to validate my application configuration upon startup. Especially when doing local development, I want to know which application settings are missing. I also like to know where I should add them. This blog shows how to implement validation of your configuration classes using data annotations.
Use data annotations
The configuration classes were completely rewritten when .NET Core was introduced. We came a long way since the old .config files.
I love how we can now use the options pattern to bind our settings classes. Strongly typed instances are injected as
IOptionsSnapShot<T> into our services.
Let’s define a settings class and use data annotations to make the fields required:
What does .NET Core provide?
Microsoft introduced a validation method that can validate the options (since .NET Core 2.2). You can use it with data annotations and it can look something like this:
This is what happens when you try to read the
Value of the
.NET throws an error upon usage and the error message does not provide many clues on what to do or where to look.
If you, like me, are looking for eager validation on startup, you must wait until the next version:
Eager validation (fail fast at startup) is under consideration for a future release.
Source: Options pattern in ASP.NET Core — Options Validation
So, we need to code something our selves.
PostConfigure to the rescue!
PostConfigure to validate the created option and throw an error if something is invalid:
Now, when we run the code, it breaks in (and during)
Startup.cs. This is eager validation, and it provides us with an exception that helps to solve the configuration-error.
Your startup can get quite verbose if you have to configure many options in your application. That’s why I’ve created the following extension methods to help set up the configuration and validation of options:
Coming up with a good name for an extension method is usually the hardest part. Normally, I set up options using
ConfigureAndValidate<KafkaOptions>("Kafka", Configuration) looks good to me.
Let’s look at an example application. I like to use the
appsettings.json to define the configuration of my services. This is the
This setup allows us to use environment-specific configuration files. Next, we’ll set up the loading of the configuration information into an object in the
Note: the configuration is injected in the startup class.
Because we’ve used
config.AddEnvironmentVariables() in our program, the setting values could also come from the environment. Technically, we can add a
Kafka__GroupId to satisfy the requirement.
Configuration can come from a myriad of places, not just from the config files. Pointing your fellow developers into the right direction can save a lot of time.
I work as a Lead Developer at Wehkamp.nl, one of the biggest e-commerce companies of the Netherlands. This article is part of our Tech Blog, check it out & subscribe. Looking for a great job? Check our job offers or drop me a line on LinkedIn.
Originally published at keestalkstech.com on September 20, 2019.