ASP.NET Core – make sure IOptions<T> is initialized

1. Introduction

As most people know IOptions<T> is a convenient way of handling configuration options in your application. Even though I’ve been using it for quite some time, last week I was unpleasantly surprised by a production bug caused by wrong usage of this mechanism.

2. Problem

Let’s say we have a simple controller which depends on two instances of IOptions<T>

Then we add only IOptions in Startup class – IOptions<PaymentOptoins>

Now, when we run the app and hit one of the endpoints in ValuesController I was expecting to get an exception, as I didn’t register IOptions<NotificationOptions>. Surprisingly for me, the application was running normally and IOptions<NotificationOptions> was created with the new instance of NotificationOptions class(with all the properties defaulted).

In order to find out why it behaves like that we have to take a look how services responsible for handling IOptions<T> are registered in the container.

As you can see AddOptions method registers open generics for (among others) IOptions<> which means that you don’t have to register specific types of IOptions<T>, however, you are responsible for its configuration with

I was always convinced that services.Configure registers and configure IOptions<T> but apparently, I was wrong.

3. Ensuring initialization

As these kind of errors are rather difficult to catch(at least in case of our application) I wanted to minimize the risk of doing the same bug again. The idea was to make sure that at least one IConfigureOptions<T> or IPostConfigureOptions<T> service is registered in the container (as these are the services which are responsible for setting the values of T class). My first approach was to replace default OptionsFactory<T> with a custom one

This method works fine (although probably needs smarter TOptions filter)

however I got to conclusion that there is no point to do validation in a runtime, and the integration test might be a better choice. I came up with following code (I am assuming that all configuration options are stored in the same assembly, as this is convention in my project)

Running the test shows that NotificationOptions was not configured

Source code for this post can be found here

ASP.NET Core – make sure IOptions<T> is initialized

ASP.NET Core – passing command-line arguments to Startup class

1. Introduction

I usually pass configuration to my web API via JSON files, but recently I needed to pass them also via command-line arguments. As the solution for ASP.NET Core 2.x is quite different than for ASP.NET Core 1.x I decided to describe both methods in here.

2. ASP.NET Core 2.x

For the newest version of ASP.NET Core, the solution is pretty straightforward as IConfiguration is injected by default to the Startup class. All we have to do is to add CommandLineConfigurationSource to IConfigurationBuilder when configuring IWebHost. CommandLineConfigurationSource is part of the Microsoft.Extensions.Configuration.CommandLine package and can be easily used by AddCommandLine extension method

Now we can access our command-line arguments just like any other configuration

3. ASP.NET Core 1.x

The solution for ASP.NET Core 1.x requires a bit more work but it is possible to achieve the same result. We still will be using CommandLineConfigurationSource from Microsoft.Extensions.Configuration.CommandLine package, however this time we have to manually create IConfiguration object and register it in the container before the Startup class is created. This is possible because the WebHostBuilder exposes ConfigureServices method.

Having our service registered now we can easily access IConfiguration object in our application


Source code for this post can be found here

ASP.NET Core – passing command-line arguments to Startup class

ASP.NET Core – retrieving swagger specification without hosting API

1. Introduction

I am currently exploring possible ways of removing a repetitive work when it comes to creating integration tests for our API. The one thing which usually takes some time when testing a new endpoint is a process of creating response and request classes (as we don’t share the models between API project and integration test project). That is why I would like to have some kind of a tool (AutoRest or NSwag) which would do it for us (possibly, in a prebuild step). As those tools generate API clients based on swagger specification and I wanted this process to be as fast as possible I decided to figure out the way how to retrieve swagger specs without hosting the API.

2. Implementation

After taking a look at Swashbuckle.AspNetCore.Swagger source code it turned out that Swashbuckle.AspNetCore.Swagger.ISwaggerProvider is responsible for creating a SwaggerDocument class. JSON representation of that class is a swagger specification. Having all of that in mind I wrote following piece of code.

The Program class is an entry point of the API. The only one difference compared to default ASP.NET Core template is the fact that I made the BuildWebHost method public. Thanks to that we can build the host (but without running) and get our hands on the DI container of our application. From that point the rest is easy, I retrieve the ISwaggerProvider from the container so I can get the swagger document for given id.

In order to make sure that the SchemaRetriever works as expected I wrote simple integration test which makes sure that swagger specs from hosted API is the same as the one retrieved without hosting.


Source code for this post can be found here

ASP.NET Core – retrieving swagger specification without hosting API