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

ASP.NET Core MemoryCache – GetOrCreate calls factory method multiple times

Recently I’ve been trying to locate a performance issue in our application. Stress tests have shown an excessive usage of memory combined with too many external server requests. As usual in such cases, I’ve run the profiler and after a bit of searching, I’ve noticed that issue is connected with our caching mechanism. The problematic part was a factory delegate (responsible for populating cache, if the cache for given key is empty) which was called multiple times when concurrent requests were sent. That was a bit surprising to me as we basically were using a very naïve wrapper over ASP.NET Core MemoryCache.

However simple test proved that this was an actual issue

After doing a bit of a digging it turned out that this was by-design behavior, which is documented in the very end of official documentation . However, as this behavior wasn’t the one we were expecting, we decided to reduce amount of factory calls by applying custom logic. We had couple of ideas when it comes to implementation, including:

  • Exclusive lock over factory method
  • Lock per key
  • Lock per type

After discussion we decided to go with third option, mainly because we didn’t want to over-complicate the design, plus we wanted to allow concurrent factory method calls for different types of objects. Once CacheService was updated with following code

we stoped experiencing excessive memory usage.

Source code for this post can be found here

ASP.NET Core MemoryCache – GetOrCreate calls factory method multiple times

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

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