Monday, January 17, 2022

Azure DevOps–Run GraphQL Inspector as part of your build pipeline

I introduced GraphQL Inspector in a previous blog post. Let’s see today how you can integrate it into your Azure DevOps pipeline.

You can do this by adding a command line task that invokes NPX. NPX stands for Node Package Execute and it comes with NPM. It is an npm package runner that can execute any package that you want from the npm registry.

I added a command line task to invoke npx:

Remark: I blogged about NPX before(using GraphQL Inspector as an example).

Something you should really be aware of is the order of the parameters when invoking graphql-inspector. The first parameter should be the existing schema and the second parameter should be the new, updated schema.

Today I accidently switched them around which of course broke the backwards compatibility.

Here is the build output when using the wrong argument order:

And here is the build output after fixing the order:

Friday, January 14, 2022

ASP.NET Core–Mark a web api as deprecated

Versioning of your API’s in ASP.NET Core is easy thanks to the Microsoft.Aspnetcore.Mvc.Versioning nuget package. It allows us to implement versioning with a few configuration lines.

After installing the Nuget you should update the ConfigureServices() method in Startup.cs:

Now you can add the [ApiVersion] attribute on your controller:

If you now have multiple versions of your api, you can decide which version to use by adding an ?api-version=1.0 at the end of your url.

So far nothing new. A feature I only discovered recently is that you can also flag an API as deprecated.  Therefore you need to set an additional Deprecated property on the attribute:

When a client now calls the deprecated API, an extra response header ‘api-deprecated-versions’ is returned:

api-deprecated-versions: 1.0

Thursday, January 13, 2022

ASP.NET Core - Configure file upload size limits

By default, ASP.NET Core allows you to upload files up of (approximately) 28 MB  in size. However, for an application I had to update this limit to support files up to 128MB.

Let’s see what should be done to get this working in ASP.NET Core:

Open your Startup.cs and write the following code in the ConfigureServices():

The code above configures the FormOptions and sets the MultipartBodyLengthLimit property to 128MB.

Unfortunately we are not done yet. Depending on if you use Kestrel or host your application in IIS (Express), some extra work is required.

IIS (Express)

For IIS (Express) you need to update your web.config and add the following configuration section:


For Kestrel, you need to add some extra code in your Program.cs file:

Wednesday, January 12, 2022

C# - Case-insensitive Enumerable.Contains()

While writing tests for an application, one test I created failed unexpectedly.

The code it tested was the following:

This code reads all querystring parameters from the current request excluding a set of predefined parameters. I use this code to capture all query string parameters that are not explicitely bound to an action method parameter:

Do you spot the bug? The problem was that this code only worked when the query string parameter name has the same casing as the parameter names in my code. If the casing was different not all parameters where excluded.

To explain this further, following querystring worked as expected:


Whereas the following querystring didn’t do the trick:


To fix it, I had to update the Contains() check to be case-insensitive. This can be done by using an overload that allows you to specify an IEqualityComparer<T> implementation.

First I was thinking I had to implement this interface myself, but luckily a built-in solution exists through the usage of the StringComparer class:

The StringComparer.OrdinalIgnoreCase implementation was exactly what I needed…

Tuesday, January 11, 2022

Github - Deploy a Nuget Package on a new release

I have a small library that I created a few years ago to use PostgreSQL as a distributed cache in .NET core.

As I wanted to get more acquainted with Github and all it possibilities, I thought it was a good occasion to make some improvements and optimize the deployment process. (I manually pushed the first version of the package to

Let’s see how we can automate this by combining the Release functionality in Github with Github actions.  

Create the Github actions workflow

Let’s first create a workflow that does the following:

  • Build the library
  • Create the NuGet package
  • Upload the NuGet package to

Therefore we go to our Github page and select Actions.

Choose New workflow.

We will not use one the suggested workflows but want to create our workflow from scratch so click on set up a workflow yourself.

Now we’ve finally arrived on the Edit workflow screen.

Replace the existing workflow definition with the following:

What is important to notice in the workflow above:

  • The workflow is triggered when we publish a new release(more about this later)
  • We use the tag_name value that can be specified during a release to update the package version:

dotnet pack --configuration Release --no-restore /p:Version=${{ github.event.release.tag_name }}

  • The api key required to push our package to is managed outside the workflow and stored as a Github secret using ‘NUGET_API_SECRET’ as its name:

dotnet nuget push **/*.nupkg --api-key ${{ secrets.NUGET_API_SECRET }} --source

Set the secret

To set the secret we need to go to Settings.

There we need to go the Secrets section and create a new secret using the New repository secret button.

Specify a name(in this case NUGET_API_SECRET) and a value:

Create a release

Now we can finally create a release. On the home page of your repo click on Releases on the right.

On the Releases page, click on the Draft a new release button.

Hit Choose a tag and enter a new release number here e.g. 2.0.2. What is important here is that this number is a valid NuGet package version number because it is this tag value that will be used inside our workflow.

Click on Publish release.

This should trigger the workflow and after a few minutes, you should see a succesfull run of the workflow on the Actions tab.

Monday, January 10, 2022

NuGet–Add a README to your NuGet Package

Did you know that yu can pack a file in your NuGet Package and that it will be rendered on supports this (new) feature for some time but I didn’t had time so far to try it out. 

To use it, you need to have first of all an file in your Repo. This is already the case for my Extensions.Caching.PostgreSQL repo:

Now I need to update my project file and reference the

After deploying the updated package, my Readme file becomes visible on

More information:

Friday, January 7, 2022

Towards more diversity–Becoming a more inclusive IT industry

As a priviliged white male, it is maybe not up to me talk about diversity. But I want to help and I try to move from being unconscious incompetent to (at least) conscious incompetent when talking about diversity.  My eyese are opening slowly and I start to be aware how lucky I am and how hard it must be for people with different color, religion, background, gender,… to work in our industry.

Working in a male dominated industry(IT) where we are continuously looking for new talent, being more inclusive will be an important part of the solution. It is our responsibility to make this possible.

I want to share 2 talks that helped me open my eyes:

One is by Kent Beck, titled “XP as an incentive system”. The title doesn’t match the content as it is a shout out to everyone to become more inclusive and forces us to think on how we are behaving and how maybe we (unconsciously) contribute to the problem instead of being part of the solution.

The second video is a TED talk “Why do so many incompetent men become leaders? by Tomas Chamorro-Premuzic. I think the title says it all…

Here is the related article:

Thursday, January 6, 2022

Error MSB3030: Could not copy the file "StaticWebAssets.xml" because it was not found.

A collegae contacted me today with the following question; his builds started to fail suddenly with the following error:

##[error]C:\Program Files\dotnet\sdk\6.0.101\Microsoft.Common.CurrentVersion.targets(5100,5): Error MSB3030: Could not copy the file "StaticWebAssets.xml" because it was not found.

He was wondering if something was changed on the build server and indeed he was right; we recently installed the .NET 6 SDK on the build server.

As you can see in the error message, the project was built using the .NET 6 SDK.

To fix the error we provided a short and long term solution.

The short term solution

The short term solution was triggering a clean solution before building the project. This will remove all remaining build artifacts and guarantees a clean slate.

To achieve this in Azure DevOps using the Classic pipeline:

  • Go to your Build pipeline
  • Select the Get Sources Tab
  • Set the Clean value to true
  • Save the pipeline and run the build

 Remark: This also fixes the problem in Visual Studio, do a Clean solution before triggering a build.

If you are using the yaml pipelines, you can set this at the workspace level:

The long term solution

To avoid this problem in the future, you can define the SDK version that should be used through a global.json file:

You can create a new global.json file in the current directory by executing the dotnet new command, similar to the following example:

dotnet new globaljson --sdk-version 3.1

Wednesday, January 5, 2022

Swashbuckle - Free form query parameters

I’m creating an api where an arbitrary number of query parameters can be added.

The API looks something like this:

GET /api/example?param1=value1&param2=value2&param3=value3

By default when Swashbuckle generates the Swagger UI it only includes parameters that are explicitly defined at the action method level.

Luckily the Open API spec supports this starting from version 3 through ‘free form query parameters’.

At the spec level this looks like this:

To achieve this using Swashbuckle you can use an operation filter:

This will generate the following UI: