The only source of knowledge is experience

The hidden maintenance cost, bitrot!

Sometimes it is very hard for customers to understand the hidden costs involved when you build custom software. By a hidden cost, I mean a phenomenon that apparently is back in our industry called BitRot.

What is BitRot?

Back in the day, BitRot was caused by the fact that the magnetic media we used to store our computer programs sometimes lost their magnetic information, causing problems reading the data back. With the industry moving to new ways to store data, like solid-state drives, the problem is still there but not predominant visible anymore. We have algorithms stat store our data in such a way the lost data can be recovered, and from an end-user perspective, it seems to have vanished completely.

Data degradation – Wikipedia

Bitrot redefined

So although the original problem has gone more or less away, we are now confronted with a completely new way that bitrot is coming back in our industry. You might disagree with me about reusing the name BitRot for something different, but in essence, the problem we face manifests itself in the exact same way. If we don’t touch the software, we write for even a few weeks, the software deteriorates!

Let me explain what is going on here.

BitRot today is the issue when we don’t touch our software for a few days or weeks, and the software deteriorates caused by a number of sources. Let me share a few of the issues you will face when building software today

New known vulnerabilities

A known vulnerability is some weakness found in the software you wrote or in any software you used to build your application or website that can be exploited by someone. You might think, why would my software all of a sudden become exploitable while I haven’t touched it? This is caused by the fact that attackers become smarter each day. they find new innovative ways to exploit software and since the software that is written often contains tons of code not only written by your own company but also open source components, the chance of your software becoming vulnerable itself is a significant risk. This does not immediately mean your software will be exploited as well, but the likelihood your software becomes exploitable will increase almost every day. This is something that you need to keep track of and you need to make updates or changes to your software to keep up with the current state of the industry. The number of vulnerabilities found is also increasing all the time. You can see how fast this is picking up in the following graph that is published NVD – CVSS Severity Distribution Over Time (nist.gov). I added a capture of the graph you can find there, that shows how many known vulnerabilities are found and that the rate of finding them is constantly increasing.

NVD – CVSS Severity Distribution Over Time (nist.gov)

Updates of used frameworks or packages

Your software is rarely built from scratch. To build software, you will use other software components all the time. Depending on the technology you use to write your programs, you use NuGet packages (.NET), Maven packages (Java), Node Packages (Node/Web Development), RubyGems (Ruby development), etc. These packages are built and maintained by others. and coming back to the previous topic, they also need to maintain their software to keep it free from known vulnerabilities. Also, they want to provide new capabilities and features constantly. This implies those packages will get new versions all the time, and keeping up with those more recent versions is not to take lightly.

Let’s assume you build a simple Hello World web application using .NET 6. and React to give a simple example. You can see the screenshot of what I did to create the application in Visual Studio 2022:

New ASP.NET with React project

Then this will result in the astonishing set of 1,487 Dependencies from the NodeJS ecosystem and 15 more from the .NET ecosystem. Starting with a clean template (I updated everything before I created the application in visual studio), this already resulted in 23 Known Vulnerabilities of which 9 are at the level of High!

Analysis of new project with Dependabot (GitHub)

Updates on compilers and tooling

Then there are the dependencies on Visual Studio 2022, which has updates at least once every month. Then we took a dependency on the .NET framework that is updated at least 1x per year and every two years has a new stable release that is supported for a maximum of 3 years. And finally, we took a dependency on the NodeJS toolset, which is also updated multiple times a year. These tools also tend to make breaking changes. You need to constantly keep them up to date because they can also contain known vulnerabilities that might compromise your development environment!

Newer versions of the languages and frameworks

Finally, there are also dependencies on the languages we used. In this example, I used React which is Javascript/typescript based, and C#10 for the .NET codebase. C# updated on a yearly cycle, and if you look at the versions of Node, then you see you need to update this every six months:

Releases | Node.js (nodejs.org)

Those language and framework updates can be significant if you look at the amount of work involved to actually use the new capabilities. Not using them still makes your codebase deteriorate from a maintainability perspective since the industry is moving on with new ways of utilizing the language and framework features. New team members on a project will have a hard time adapting old programming styles and inefficiencies if you only ensure it compiles.


The software you build is in a constant state of decay, and you need to allocate a significant portion of time to keep things evergreen and up to date. Waiting for your updates will cost you significantly more time than updating constantly. Also, here you see, the adage “if it hurts, do it more often” applies and makes the software delivery cadence more predictable and more secure. So make updating packages, frameworks, and languages part of the standard maintenance cycle!

The real challenge lies in making our customers aware of this problem and finding ways to make them aware they need to maintain software. You can not let software untouched for a few weeks since, in the meanwhile, the software becomes outdated and vulnerable. And last but not least it will become more complicated each day to make it up to date again.

Troubleshooting Appium Tests with a logfile

Sometimes you can run into issues when you run Appium. This can be caused by a driver mismatch or a version upgrade of Appium, or some configuration change on your machine. But how do you figure out what is going wrong?

The best way to troubleshoot is to get your hands on the log file that Appium can produce. But where is it located? That was my major issue when troubleshooting. The log files themselves often contain a ton of good information to help you solve the problem.

How to set up the logfile?

You can get a log file by adding a startup command-line argument and specifying the log location. So when you run your tests from a build or a test in, e.g., Visual Studio, the best way to get your log files consistently is by specifying this in your test setup code.

Most of my time in coding I spend using C#. So when you use the Appium test engine with C# you can use the class ServerBuilder. ServerBuilder has the option to use the .WithLogFile option where you can specify the location of the logfile.

You can write your code as follows to startup your test and always have a log file as part of your test run:

I assume you are using MSTest as the test framework in this code sample since I use the TestContext to obtain a location where I want to have the logfile published.

Walking with RD’s

The idea of Walking with RD’s is that we provide a monthly videocast to you where we as the RDs in the Netherlands will go for a walk (because that’s one of the typical things we all do in these COVID times) and talk about a business-related topic. During this walk, we share our insights and discuss the challenges and opportunities we have faced during our career in the hope this provides valuable insights to you.

This First episode introduces the RD’s in the Netherlands and introduces the Regional Director program which is not always know to everyone in the Microsoft ecosystem.

In the Netherlands we are with five Microsoft regional directors: Sjoukje Zaal, CTO at Capgemini, Maarten Goet, Director at Wortell, Andre Carlucci, Global Director of Application Engineering at Kinley and Maarten Eekels Chief, Digital Officer and Managing Partner at Portiva and myself.

You can read more about the Microsoft Regional Director Program here, the short summary is here below:

“The Regional Director Program provides Microsoft leaders with the customer insights and real-world voices it needs to continue empowering developers and IT professionals with the world’s most innovative and impactful tools, services, and solutions.”

The topic we discuss in this episode is:

Working from home’ while still performing. How do we deal with this and what has worked very well for ourselves and the teams we work with.

This walk gave me also some new insights into how we can work from home and help and support our teams to stay healthy and sane. I really hope you will enjoy this episode and please let me know if you have additional tips and trick you would like to share, so we can all learn from each other and come out of this pandemic better than when we started. Hope you enjoy this episode and please share additional insights you might have with us as well!

And I want to thank Maarten Goet for arranging the creation of the leader and edit of this video!

Configure your ASP.NET Core application to use HTTPS that runs as a container in a Kubernetes cluster

In my course “Deploying ASP.NET Core Microservices Using Kubernetes and AKS” that you can find @pluralsight, I discuss the use of SLL inside and outside the kubernetes cluster.

In this course I made the choice to have no HTTPS between the services inside my cluster, but only to have SSL on the web frontend. But in my demo’s I did not address how I set up SSL on the website that I deploy to the cluster. In this article I want to give you some pointers how to make this work.

What do I need to get SSL on the website?

First of all you need a certificate file that can be used. Since I host the web endpoint direct as a Kubernetes service, without the use of any ingress controller, the only way to make this work is either by putting something in front of the website that will handle SSL (e.g. by using a Web Application firewall), or by handling SSL in the pod itself. You can also delegate this work to ingress in the cluster, but I did not use that in this scenario. If you want to use ingress and set up SSL that way, then you can find other articles like here, that you can follow. In this article I will go through the steps to handle the SSL communication direct with the kestrel server that runs inside the pod. Setting up kestrel to use the production certificate. Because we set up SSL without the use of the ingress controller this implies that the request will be handled by the actual pods that host the website. For this we need to make some tweaks to the ASP.NET core website startup, so it accepts the certificate file I have for the domain globoticket.com.

Get a certificate file that can be used to configure SSL for production on ASP.NET Core

ASP.NET core runs on the Kestrel server when you build the website in a docker container. You can configure the kestrel server to use a certificate to host the website on the domain name you have for your production environment. For this I used the capabilities you can find in azure to create a so called App Service Certificate. This is normally used to create a certificate that you can bind to an APP Service. In my case I just wanted to get the certificate and export it so I can then deploy it to the Kubernetes cluster as a secret and then use it in the container to configure the server.

When you create the app certificate and you imported it into a keyvault, you can export it as an PFX file using a few lines of PowerShell. there is an article you can find here that contains that PowerShell script that you can use.

Now we have an PFX file, and we can use this to configure the server. For this we can use two options. One is to make a change to the codebase and configure kestrel to use the pfx file with a password that you provide. My first idea wat to use this and then provide the PFX file as a file mounted to the pod, but this was more challenging then I thought. There is no simple way to just upload the pfx file to the cluster as a secret and then mount it to the pod. This is because you cannot set a secret to just contain a binary file. Instead I was required convert the pfx file to a base64 encoded string, that I can upload as a secret to the cluster.

To create a base64 encoded string from the pfx file you can use the following lines of PowerShell:

Because I now have a pfx file that is not understood by default by ASP.NET core I also needed to change a bit of startup code. At startup I save the pfx file to local storage and then configure Kestrel using environment variables to pick up the certificate file and the password.

For this I leverage the environment variables ASPNETCORE_Kestrel__Certificates__Default__Password and ASPNETCORE_Kestrel__Certificates__Default__Path When these are configured then the server will pick up the pfx file and configure SSL automatically, without any additional code changes

The way I solved this is by creating a new environment variable that I called base64pfxfile and I provided it the value that I first pushed to the cluster as a secret. This can be done with the following configuration:

This keeps the config file clean of any secrets and it passes the base 64 encoded string to the container as an environment variable.

I had to change the startup code of the ASP.NET website to decode the string, save it to a local file and then configure the environment variable ASPNETCORE_Kestrel__Certificates__Default__Path to point to the file. The Password is passed in the configuration in the same way. I created a secret and pass that secret as a value to the environment variable ASPNETCORE_Kestrel__Certificates__Default__Password

The startup code was changed as follows:

The way to create the secrets is as follows:

Now we have all the ingredients to make it work.

Next you can push the changes to the azure DevOps or GitHub repo and then let the GitHub Action or Azure DevOps pipeline run the build and deployment to the cluster.

The final step was to configure the domain name globoticket.com point to the IP address that is used by the Service endpoint and browse to the website.


Hope this helps setting up SSL on your externally exposed website endpoint. I made the choice to do it direct in the pod, of course there are also other ways. You can also set up the ingress controller to take care of the SSL termination and then pass through the request to the web pod.

How to Fix: Login failed for SA when running MS SQL Server on Linux in a Docker container

TLDR; It seems the documentation on how to start the Linux based sql server container contains a bug! The documentation states you need to start the container using the following command-line:

But this is wrong, because it will not set the password for SA

It took me hours to discover the environment variable they actually use to set the SA password is ‘MSSQL_SA_PASSWORD’

So when you use the following command line it just works

Hopefully it will save you from pulling your hear out and also searching for hours. I filed this as a bug, hopefully the docs or the scripts are updated soon. Github Issue

Steps to reproduce:

  • Run the command-line as advertised in the documentation to start the container.
  • Run a docker exec command to run a bash shell in the container interactively
  • Run the following command:

This will give you the following error:

Now remove the container and try again, but replace the -e ‘SA_PASSWORD=yourStrong(!)Password’ with -e ‘MSSQL_SA_PASSWORD=yourStrong(!)Password’

Try the same steps again, and voila, you are connected to the SQL server.

How to solve sporadic crash in Xamarin App with async and await

TLDR; Make sure all your async methods return a type of Task<something> and not just Task or Void! this will cause sporadic crashes of your application. Only use asyn void or async Task on event handlers.

Longer version:

Recently I worked on an app build in Xamarin and found myself in a nasty situation. My app would crash in the debugger and leave no trace what was going on. In the device Log I could find the following message:

Time Device Name Type PID Tag Message
04-08 18:22:28.908 nexus_api_27 Error 4058 DEBUG Abort message: ‘* Assertion at /Users/builder/jenkins/workspace/xamarin-android-d16-0/xamarin-android/external/mono/mono/mini/debugger-agent.c:4407, condition is_ok (error)' not met, function:set_set_notification_for_wait_completion_flag, <strong>Could not execute the method because the containing type 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder1[System.Collections.Generic.IEnumerable`1[T_REF]]’, is not fully instantiated. assembly: type: member:(null)

The nasty part was that when you step through the code in the debugger the application would just crash under your fingers and you could not step through the code that was causing this. And this message is useless as well since it does not show where things go wrong. Only stepping through the debugger revealed a part of the code where the debugger would exit without any message and the app crashed as well.

You can see at various placed more developers experience this issue. e.g.:


The code that was causing the crash looked as follows:

The issue lies in the method calls that have await, but don’t expect a result.

The signatures of the methods InitializeStore(), PullLatestAsync() and AnnotateFavorites() all returned a Task, but not a Task<T>. This results in the fact that the method call is more or less fire and forget method and you don’t really have to wait for the result to be returned.

It is important that you change the method signatures to e.g. return a Task<bool> where the boolean is only signaling success or failure of the method call.

I was able to rewrite those methods to all return a boolean value and this resolved the issue of the method exiting without any results.

You can find more on best practices of using async and await here: https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

Hope this helps you resolve this issue as well.

Override classic ASP.NET web.config Configuration Settings When Using (Docker) Containers

One of the challenges with ASP.NET in combination with containers, is the fact that you configure all your settings in the web.config. when using containers, we want to provide different settings for different environments we run our containers. E.g. you have a dev, test, acceptance and production environment, for which you want other connection strings and appsettings for your application.

Containers bring us the concept of immutability, meaning that once we bake our container, it is fixed. This implies that when we want to change settings in the web config per environment we are more or less stuck.

ASP.NET 4.7.1. to the rescue!

In ASP.NET 4.7.1 Microsoft added some awesome new capabilities to override your web.config settings using other mechanisms like environment variables.

The way this works is that you can now add configuration builders to your web.config file. You can build your own configuration builders, or use some of the pre-cooked configuration builders that Microsoft provides. One of them is particularly handy, since it helps us to override values in the web.config based on environment variables. And that exactly matches what we need to run in containers!

How do we use configuration builders?

Let me show you how to make this work for an legacy application we all know and love: The MVC Music Store.
First of all you need to set your target framework to .NET framework 4.7.1. or higher.


If you don’t find this target in your dropdown, you can install the developer packages here and install them, so they show up in Visual Studio.

In your web.config file you can now add a new configuration section handler, that will enable you to add attributes to various sections where you want to have an override of the configuration.

Here is the way you add configuration builders to your config:

After we added the configuration section, we can now specify which configuration builders we want to use. You can build your own, but you can also use the one provided by Microsoft. they have a couple of them, I am using the one to use environment variables.

Before this will work, you need to ad two nuget packages to your application, otherwise it is not able to find the assemblies mentioned in the config file.

You need the following packages:


Microsoft.Configuration.ConfigurationBuilders.Base is the infrastructure to intercept any calls to web.config to read configuration and it provides the option to have a configuration builder override the values in the current file.

Microsoft.Configuration.Configurationbuilders.Environment is the implementation to read from environment variables and override specific sections of the web.config file. The sections supported at the momen are: Connectionstrings, where you can replace the connectionstring value (not the providerName!) and the appsettings section in your config file.

The way to let a part of the configuration to be overridden is by adding an attribute to the section. For appsettings this looks as follows:

For your connection string it looks like follows:

You see in both sections we added an attribute that tells the configuration builder, which configuration builder to use to override the values. You can use multiple configuration builders that you configure for different sections. One builder is used per section.

Overriding the values

The syntaxt to override your app settings is quite straight forward. You can set an environment variable with the name of the app setting and provide it a value. E.g. overriding your ApplicationInsightsKey would be done by setting an environment variable with the name ApplicationInsightsKey and give it a new value.

For connection strings you also provide the name of the connection string and the value will then override the current connectionstring attribute. Overriding the connection string for MusicStoreEntities you provide an environment variable with the name MusicStoreEntities and give it the value of the connectionstring you want to use.

At the moment there is no solution yet for more complex settings, but you can build your own configuration builder to take care of this. How to build a configuration builder is described here:Writing a configuration builder

Using this in your containers

If you have build your container with a docker file, you can now very easily override your settings from the commandline.

I have created a docker image you can pull from docker hub to show you that it works. If you just pull the image : marcelv/mvcmusicstore-configbuilder and you provide it a connectionstring for a database you want to connect to it will show you the mvc musicstore using configuration builders.

You can run it as follows:

If you don’t have a database available, just use an docker container for that.

To start a sql server to be used with the music store, use the image : microsoft/mssql-server-windows-developer

To make this work together (without creating a compose file), first start your SQL server eg. like follows:

This will return you an id for the container that runs.

Now run the command:

Now the id you find for the sql server is what you can use as the host name of the sql server in the connectionstring.
Let’s assume it returned the number : 8bf45f8935c6

Now you can start the mvc music store container as follows:

Now you can browse to localhost with your browser of choice and you should see the MVC music store there.
(assuming you are on docker for windows 17.12.0-ce or higher, otherwise you need to browse to the ip address of the container. You can get this info by either running ipconfig in your container with docker exec command or by using the docker inspect command on the container id)


By using the new configuration builders you can override the values you normally have in your web.config file. This enables us to use containers in a very simple way with our classic ASP.NET applications. No need to move your site to .NET core, just to get environment variable support for your configuration. This should enable you to leverage the immutability of containers even for your existing classic ASP.NET applications!

Just released: Introduction to Docker on Windows with Visual Studio 2017

In this new course, I teach you how to use Docker to deliver solutions to the Windows platform. First, you’ll explore the options and capabilities Docker offers on the Windows platform. Next, you’ll delve into how Visual Studio 2017 simplifies the use of Docker in the development cycle. Finally, you’ll learn how to implement a delivery pipeline with Visual Studio Team Services (VSTST) or TFS to deploy to any of the target platforms, ranging from single windows server to a cluster of machines managed by cluster managers like Kubernetes or Service Fabric. By the end of this course, you’ll be able to explain how containers work on windows, how to build Docker containers to run new or existing workloads, and how to deploy your applications to different container hosting solutions on premise or in the cloud.

Here is a brief video introduction that gives you an idea of the course.

Here is the outline of the course:

Module 1: Introduction to Docker on Windows with Visual Studio 2017

  • Running Containers and Docker
  • What Is a Container?
  • Containers vs. Virtual Machines
  • Containers vs. Docker
  • Docker Command-line
  • Difference Between an Image and a Container
  • Inspecting Images and Layers
  • Running on Windows
  • Development Tools
  • Docker Compose
  • Docker Commands Needed to Understand Visual Studio
  • Which .Net Framework to Choose?
  • Container Clusters

Module 2: Docker and Visual Studio

  • Using the Docker Tools in Visual Studio 2017
  • Docker Files Added
  • The Docker file Debug/Release Trick
  • Yaml Files Added
  • The Yaml File Trick
  • Volume Maps on the Containers
  • Use the Visual Studio 2017 IDE to Build Containers
  • Debugging Your Cross-container Solutions with Visual Studio 2017

Module 3: Handling Data in Containers & Testing

  • Handling Data in Containers
  • Setting up Volume Mappings to Manage State
  • Using the Volume Mapping Commands
  • Running SQL Server in a Container
  • Creating and Running SQL Server Images
  • Leveraging Immutability for Testing
  • Integration Test Using a SQL Container That Resets After the Tests

Module 4: Docker and Your Continuous Delivery Pipeline in VSTS

  • Understanding Containerized Builds
  • Running a Build in VSTS
  • Setting up the Build
  • Configuring Build Agents to Build Containers
  • Setup a Custom Build Agent
  • Setup a VSTS Build for Your Containers
  • Understanding Tags
  • Deploying Your Containers Using the Release Pipeline
  • Deploy Your Containers to a Container Host
  • Pushing Images to Azure Container Registry or Dockerhub
  • Create and Use an Azure Container Registry

Module 5: Deploying to Azure Container Services (ACS)

  • Why Do You Need Clusters?
  • Understanding Azure ACS
  • Create an ACS Cluster Running Kubernetes
  • Deploying Your App to the Cluster by Hand
  • Kubernetes Cluster Anatomy
  • Deploy Containers to Kubernetes Cluster by Hand
  • Deploying Your App to the Cluster Using VSTS
  • Zero Downtime Deployment Using VSTS and ACS with Kubernetes
  • Scaling Your Apps and the Cluster
  • Alternative Cluster Solutions

Module 6: Deploying to Azure Service Fabric

  • Understanding Azure Service Fabric
  • Same Rules Apply as to ACS
  • Create a Service Fabric Cluster
  • Deploy Containers to Service Fabric by Hand
  • Deploy Containers to Service Fabric with VSTS

You can find the course here at the PluralSight website: https://app.pluralsight.com/library/courses/docker-visual-studio-2017-windows

Not yet a PluralSight subscriber? No worries, you can still watch the course for free with a trial subscription.

Hope it helps to get you up to speed with Docker on Windows!

« Older posts

© 2024 Fluentbytes

Theme by Anders NorenUp ↑