ASP.NET Core 1.x – curios case of missing IOptions<T> array item

1. Introduction

Last week while I was working on one of the features for my current project, I noticed quite surprising behavior of IOptions<T> object. Long story short, for some reasons there were missing array elements in my parsed application settings class.

2. Problem

Just like everyone else, we store our application settings in JSON file. The settings are pretty straightforward, just a bunch of properties with some nested objects

which are bound to the AppSetting class thanks to these couple of lines of code

where AppSettings class looks as follows

As you can see nothing too fancy in here, standard ASP.NET Core approach for handling configuration files. However, if you access the PaymentMethods property of IOptions<AppSettings>

you will see that instead of four elements we ended up having 3 items

as the “Visa” element is missing.

3. Solution

If you look closely at the appsettings.json file you will notice that a “Visa” item configuration is a bit different than the ones which are parsed just fine. Namely null is assigned to excludedCurrencies property, whereas in other items an empty array or no property at all is used. So the first fix is just to use the same approach as in the other items

This approach works fine, however, it is not a silver bullet as someone still might use null and introduce a bug. Another fix might be upgrading to ASP.NET Core 2.0 as the problem doesn’t seem to exist in there. Of course, this is rather a huge change so not everyone will be willing to do it. The last option is a manual installation of Microsoft.Extensions.Configuration.Binder 2.0 along with Microsoft.Extensions.Configuration.Json 2.0 package. However, this approach requires you to retarget your application to netcoreapp2.0. One way or another every solution in here works fine, so once you apply the fix you will see all items in the array
Source code for this post can be found here

ASP.NET Core 1.x – curios case of missing IOptions<T> array item

ASP.NET Core – request serialization issues after migration from classic WebApi

We’ve been migrating a classic WebApi application into the ASP.NET Core API for quite a while now, and last week we decided to deploy it on the test environment and try to run a website against it. We were pretty confident about the quality of a migration because all of the integration tests from old API were green when running against a new one. We were expecting maybe some business logic bugs but from our perspective, the infrastructure part was good to go. Unfortunately, when the QA’s run the selenium test suite they quickly found a major issue in our codebase. They basically were getting HTTP 500 errors indicating a NullReferenceException. That was pretty surprising to us and after a bit of a digging we found following lines in the logs

this was resulting in a null request in controller’s action
As you can see JSON serializer was not able to convert null into the int. We double checked the requests coming from front-end and this is how one of them looked like

whereas corresponding request class on the server side was written in following way

Clearly front-end shouldn’t be sending a null as a PassengerNumber however the same request was serialized just fine when running against classic WebApi
Fortunately the fix for that was pretty straightforward. All we had to do was to configure JSON serializer to ignore null values.

From now on we were able to properly serialize the request
Source code for this post can be found here

ASP.NET Core – request serialization issues after migration from classic WebApi

NLog.Web.AspNetCore – make sure you add error message for logging exception

I’ve been using NLog for quite some time already, and it was a natural choice to use it in the ASP.NET Core projects as well. I’ve configured the logger using this tutorial and everything seemed to be working fine. Unfortunately, after some time we’ve noticed that for some reasons some of the errors are not logged. We’ve taken a deeper look at our code base and we’ve found couple logs being written as follows

This piece of code works perfectly fine with ASP.NET Core console logger but it seems it doesn’t for NLog.
We double checked that with following piece of code

And as you can see in the picture below, no errors have been reported

Changing the error message to any message (even the one containing only white spaces)

fixed the problem.

That looks like a bug for me, so I will create a PR with the fix and see if that will make its way to the “master”

As usual, the source code for this post can be found on my GitHub

NLog.Web.AspNetCore – make sure you add error message for logging exception

ASP.NET Core – API versioning by convention

1. Introduction

If you were looking for information about API versioning support for ASP.NET Core you’ve probably come across Microsoft.AspNetCore.Mvc.Versioning library. The library itself allows you to set up versioning in a couple of different ways, for instance, via attributes or via manual convention setup. All of this options are really nice but unfortunately, they have one significant drawback, namely, you have to set them up manually. As I tend to forget about this kind of things I wanted to automate that process as much as possible. Thankfully ASP.NET Core has a very nice feature called ApplicationModelConventions which allows you to add some metadata(like routing information, API versioning ) to your controller, actions etc.

2. Convention

I’ve decided to implement versioning by routing which means the API will be accessible via this template

The template itself doesn’t give you much, as you also have to add information to the controllers which version of API they support. In my case, I decided to go with a version by namespace convention, which means that supported version will be deduced from namespace in which given controller resides. So, in fact, there will be two conventions, one for applying routing and a second one for applying versioning

3. Creating conventions.

In order to write an ASP.NET Core convention, we have to implement IApplicationModelConvention interface. This interface has a single method Apply which takes ApplicationModel class as an argument. This class gives us access to all of our controllers, actions and other parts of the application. So if we want to apply a routing with versioning for all of the controllers, we can do it in following way

As you can see we iterate through all of the Selectors and then apply new route model to them. If selector already had a route attribute applied we combine two attributes together. Once our convention is applied our actions will be accessible with following routing prefix

or via

Having our routing ready now it is time to add versioning information to our controllers. Once again it will be done via application model convention. The version of the controller will be deduced from the namespace given controller is located in.

As you can see I iterate through all of the controller models of our application, then check the version of controller based on its namespace and finally with

I am able to inform the framework which version of API given controller supports.

4. Adding convention to application

Having all of our conventions prepared now we can enable versioning support

And of course, we have to add newly created conventions to list of application conventions

Note that I removed ApiVersionConvention and ImplicitControllerVersionConvention with simple extension method Remove<T>

to make sure that only my convention is responsible for API versioning.

Source code for this post can be found here

ASP.NET Core – API versioning by convention

ASP.NET Core – default API version with url path versioning

1. Introduction.

When you start versioning your API sometimes you want to have access to your endpoints without specifying version explicitly. Thanks to Microsoft.AspNetCore.Mvc.Versioning library this can be easily achieved with proper setup of configuration action. However, it turns out that in order to enable default API version for url path versioning, there are a couple additional steps to do.

2. Default API version without url path versioning

Let’s start with the initial setup of API versioning which will work for every type of versioning apart from url path versioning. All you have to do is to assign an ApiVersionSelector and set the AssumeDefaultVersionWhenUnspecified property to true.

Now when the user will try to access the endpoint without specifying version explicitly the ApiVersionSelector will select proper version – in this case highest available version.

3. Default Api version with URL path versioning

Running the same configuration against controllers which are versioned via url path (not query string)

will result with 404 status code, as routing is not able to match the url.
404
Fortunately, unlike the ASP.NET Web API, ASP.NET Core allows us to have multiple route attributes applied to given controller, so in order to fix the issue we just have to add

attribute to versioned controllers. From now on we can access our API without specifying version as well as with version specified.
after

4. Adding default route with convention

If you don’t want to specify default route manually for every controller, you can do it via application model convention. The interesting thing about it is the fact that apart from changing existing values of application model we can also add new items to it. This means that we can add additional SelectorModel with our default route to Selectors’ collection

Now we can get rid of [Route(“[controller]”)] attribute from our versioned controllers and just rely on convention which can be added as follows

Source code for this post can be found here

ASP.NET Core – default API version with url path versioning