Skip to main content

Posts

Showing posts from 2025

Nobody wants software

Last week I was watching a panel session recorded at the GOTO conference last year. During this session Daniel North, the originator of BDD, made the analogy between surgery and software development: No one wants surgery and if you really need it, you want the least amount of surgery to get away with. What people want is to be well and that their problems are solved. This also applies to software. This comparison of software development to surgery reveals a truth about what we're really trying to accomplish as developers. Just as no patient walks into a hospital hoping for the most complex, invasive procedure possible, no user opens your application excited about the thousands of lines of code running beneath the surface. What patients really want When someone needs surgery, they don't want surgery, they want to be well. They want their problem solved with the least disruption, the smallest incision, the quickest recovery time possible. The surgeon's skill isn...

Finding inspiration for good custom instructions for GitHub Copilot

One of the best ways to improve the results you get back from GitHub Copilot is by carefully defining your custom instructions. This helps the LLM to better understand your application, preferred technologies, coding guidelines, etc.. This information is shared with the LLM for every request, so you don’t have to provide all these details every time in your prompts. But creating such a set of custom instructions can be a challenge. If you are looking for inspiration, here are some possible sources: Awesome Copilot Instructions Link: Code-and-Sorts/awesome-copilot-instructions: ✨ Curated list of awesome GitHub copilot-instructions.md files Description: Contains a list of copilot instructions for different programming languages Cursor Rules Link: Free AI .cursorrules & .mdc Config Generator | Open Source Developer Tools Description: Originally created for the Cursor IDE but also applicable when defining custom instructions for GitHub Copilot. No examples for .NET or CSh...

Monitor your A/B test in .NET

I’ m currently working on a new feature in one of our microservices. As this new feature could have large performance impact, we did some performance benchmarks up front through BenchMarkDotNet . The results looked promising but we were not 100% confident that these results are representative for real life usage. Therefore we decided to implement A/B testing. Yesterday I showed how to implement A/B testing in .NET using .NET Feature Management . Today I want to continue on the same topic and show you how we added telemetry. Measuring and analyzing results The most critical aspect of A/B testing is measuring results. You need to track relevant metrics for each variation to determine which performs better. The most simple way to do this is to fall back to the built-in logging in .NET Core : Although this is a good starting point, we can simplify and improve this by taking advantage of the built-in telemetry through OpenTelemetry and/or Application Insights. Using OpenTelemetry...

A/B testing in .NET using Microsoft Feature Management

I’ m currently working on a new feature in one of our microservices. As this new feature could have a large performance impact, we did some performance benchmarks up front through BenchMarkDotNet . The results looked promising but we were not 100% confident that these results are representative for real life usage. Therefore we decided to implement A/B testing. In this post, we'll explore what A/B testing is, why it matters, and how to implement it effectively using .NET Feature Management . What is A/B testing? A/B testing, also known as split testing, is a method of comparing two versions of a web page, application feature, or user experience to determine which one performs better. In its simplest form, you show version A to half your users and version B to the other half, then measure which version achieves your desired outcome more effectively. The beauty of A/B testing lies in its scientific approach. Rather than making changes based on opinions or assumptions, you...

Avoiding unexpected costs from GitHub Copilot premium requests

Starting from last week June 18, 2025 an important change was activated in GitHub Copilot. From that day on you need to pay extra for any premium requests that exceed your monthly allowance. This means that we should start considering more how we use Copilot and be aware of the (potential) costs. What are premium requests? Premium requests are requests that use more advanced processing power and apply to any request that is not using the default models (GPT-4o and GPT-4.1 at the moment of writing this post). The number of premium requests you get out-of-the-box is different depending on the plan you are using: Important! Be also aware that a multiplier is applied to the cost depending on the model used. For some models (e.g. GPT-4.5) this can add up quickly as the multiplier can be as high as 50!   Disabling premium requests If you want to avoid unexpected costs, you can disable premium requests so that they don’t exceed your monthly allowance of premium requests. ...

Browse the .NET code base with the .NET Source Browser

Ever wondered how Microsoft is using some .NET features in it's own codebase? One way to find this out is through the .NET Source Browser . This site allows you to browse through all the .NET source files and find out how specific features are implemented or specific classes used. For example, I’m working on a piece of code where I wanted to use the Channels API but I was wondering how it was implemented. And what better place to learn than from the creators themselves? So I opened up the .NET Source Browser and searched for Channel.CreateBounded : This returned multiple results: When you click on a specific result you arrive at the specific source file and can further check the implementation: Another option is to go through the official .NET documentation and click on the source links there: This brings you to the code source in GitHub:   Have fun browsing through the codebase! More information Source Browser .NET API browser | Microsoft Learn

Untrusted GIT repositories in Visual Studio

For security reasons I am switching to a different account on my development machine. After adding this new account to Windows and setting up the Visual Studio configuration for this new account, I thought I was good to go. So I opened a first solution inside my fresh Visual Studio instance. Everything looked OK at first sight, but then I noticed a small warning message at the right bottom corner of my Visual Studio: And when I took a look at the Git Changes window, no changes were shown:   What is going on? Starting from Git v2.35.2 , Git now checks for ownership of the folder trying to ensure that the folder you are using Git in has the same user as the owner as your current user account. As the original Git repo(and corresponding Windows folders) was created using a different account, Git considers this repository as unsafe. This check was introduced in Git to tackle a security issue which allows parent repositories directories to override permissions of child reposi...

Detecting breaking changes in your OpenAPI metadata

For the last 2 days I have been struggling with a breaking change I had in my ASP.NET Core web api that caused the consuming application to fail. I had a header parameter that was optional but became required after changing the nullability of my project to enabled . Although I found the issue and was able to fix it quite fast, I was not happy with my current process and was wondering how I could prevent this from happening again. This brought me to a final solution where I introduced some extra tests that compared the OpenAPI metadata between different implementations. Let me show you how I did it… Generate OpenAPI documents at build time To compare 2 OpenAPI metadata documents we first need to get them. For the already released version of the API, I can download the document through the OpenAPI endpoint ( /openapi/v1.json by default). But what about the new version of the API that is still in development? I solve this by generating the OpenAPI document at build time. This m...

Making a header parameter required in ASP.NET Core

Yesterday I talked about a breaking change I had inside my ASP.NET Core web api that caused my application to fail. I had a header parameter that was optional but became required after changing the nullability of my project to enabled . My hope was that this would be visible in the OpenAPI metadata for my OpenAPI. Unfortunately, the generated metadata always looked like this: So both this code: and this code: return exactly the same metadata. The lack of a required property marks this header as optional, which doesn't reflect the actual behavior of the application after enabling nullability. I decided to investigate this a little further and found out that it is possible to emit the correct metadata by explicitly adding a [Required] attribute to the parameter: After adding this attribute the metadata was updated correctly. It’s unfortunate that ASP.NET Core doesn’t do this by default as it is aware of the possible nullability of the provided parameters.

API contracts and nullability in ASP.NET Core

Although it is not the first time that I stumble over the nullability feature and breaking changes, this one still caught me by surprise. Let me first explain the context; I have an application built in ASP.NET Core with the nullability feature still disabled. As I had to make some changes to the API, I though it was a good timing to enable the nullability feature to help me avoid nullreference exceptions. As always I started by updating the application to enable the nullability feature. Therefore set the nullable value to enabled inside the csproj file: After enabling the feature, our integration tests started to fail. Here is the specific error message that got returned: In our API we have the option to pass an optional(!) X-Environment header parameter. We use this attribute to avoid that the API is accidently called from our development or test environment. In our original API implementation this attribute is optional; in case the attribute is ommitted we don’t do the en...

Repeating a test multiple times in C#

In JUnit you have the @RepeatedTest annotation. This annotation allows you to run a single test method multiple times with different execution contexts. Unlike simply calling a method in a loop, each repetition is treated as a separate test execution with its own lifecycle. Although it can be useful to discover and investigate race conditions, I never had a good reason to start using this kind of functionality. But with the introduction of AI workloads inside my applications, times have changed. As AI output is less deterministic, it now starts to make sense to run the same test multiple times as the AI output could differ from test run to test run. Let me show you how to do this using NUnit and XUnit... NUnit: Built-in Repeat Attribute NUnit provides the most elegant solution with its built-in [Repeat] attribute: XUnit: Using Theory and Custom Attributes XUnit doesn't provide an out-of-the-box equivalent to the @RepeatedTest annotation but you can build your own ...

Improve your GitHub Copilot prompts with the Prompt Boost extension

If you are new to GitHub Copilot or other AI coding assistants, it can be a challenge to get good results as you are still learning on how to write good prompts. What if there was a way to automatically transform your basic prompts into comprehensive, context-rich instructions that consistently produce better results? Enter Prompt Boost , a VS Code extension that bridges the gap between what you quickly type and what AI models actually need to generate high-quality, relevant code. What is Prompt Boost? Prompt Boost is a VS Code extension created by Chris Dias that enhances your prompts by adding relevant technical context, best practices, and specific requirements. Instead of sending bare-bones requests to GitHub Copilot, it helps you create detailed instructions that lead to more accurate and useful responses. The extension transforms your basic prompts into comprehensive specifications. Here's a real example of the transformation: Before (Basic prompt): Create a new l...

Compiler error ASPIRE007 after upgrading Aspire

After upgrading the .NET Aspire NuGet packages to the latest version on one of my projects, I started to get the following compiler error: 'Project' requires a reference to "Aspire.AppHost.Sdk" with version "9.0.0" or greater to work correctly. Please add the following line after the Project declaration <Sdk Name="Aspire.AppHost.Sdk" Version="9.0.0" /> . The error message is self explanatory and clearly defines how we could fix this. Add the Sdk reference to your csproj file to get rid of this compiler error: The strange thing was that after applying the upgrade on one branch, I also started to get the same compiler error on other branches although the Aspire NuGet were not (yet) upgraded on these branches. Bizar! More information Compiler Error ASPIRE007 - .NET Aspire | Microsoft Learn

Property based testing - Updating FsCheck to version 3.x

f you have never heard about Property based testing, I would recommend to check my blog series about it first. But if you are too lazy to go through all these posts, here is a short definition: Property-based testing is a powerful testing methodology used in software development to verify that a system behaves correctly across a wide range of inputs. Instead of writing individual test cases with specific inputs and expected outputs, property-based testing defines properties —general rules that should always hold true for a given system. It serves as an alternative to example based testing where we focus on a set of example cases to validate the behavior of our code. There are a lot of libraries out there that help you write Property Based Tests. In .NET I mainly use FSCheck and CSCheck . As I’m doing more and more Python, I also start using Property Based Tests there through Hypothesis . In this post I’ll focus on FSCheck and how to update to the latest version as some breakin...

Speed up your Git experience by enabling the commit graph algorithm

While working in Visual Studio today I noticed a message appear at the top my idea. The message stated the following: Speed up your git experience in Visual Studio by enabling the git commit graph algorithm. No idea what that exactly means but that sounds promising… so let’s find out Why this commit graph algorithm? Git repositories can become sluggish as they grow in size and complexity. If you've ever waited impatiently for git log to load or noticed that branch operations take longer than they should, you're not alone. Recently, Git introduced a powerful feature that can dramatically improve performance: the commit graph algorithm. The commit graph is a data structure that Git uses to store precomputed information about your repository's commit history. Instead of traversing the entire commit tree every time you run commands like git log , git merge-base , or git show-branch , Git can use this precomputed graph to answer queries much faster. Think of it ...

LLM timeline

Not a long post today, just an interesting visualization I noticed; the LLM timeline . This timeline shows the fast evolution of large language models over time starting from the original "Attention Is All You Need" paper by Google researchers to today's cutting-edge models. Nice! A big thank you to Michael Gathara for creating and maintaining this visualization. More information Attention Is All You Need LLM Timeline

.NET 9–OpenAPI and Scalar–Passing an API key

Let's continue our joruney in discovering Scalar . Today I want to talk about how we can integrate security. Most API's that we build today are secured in a way. This could be as simple as an API key or as complex as using OAuth with PKCE. In this post we’ll look at how to pass an API key through the Scalar UI. Let’s dive in… I assume that you already have registered an authentication scheme for your API like this: Now we need to write an extra transformer to include the authentication information in our OpenAPI metadata. Don’t forget to register this transformer in our OpenAPI configuration: At the Scalar level we don’t have to change anything: But if we now browse to the Scalar UI, the authentication scheme is recognized and we get the option to pass an API key:   Nice! More information .NET 9–OpenAPI and Scalar–Introduction .NET 9–OpenAPI and Scalar–Adding custom headers

Get an overview of task duration of Windows Scheduled Tasks

A long time ago, we made the decision to implement some features using batch processes that were scheduled to run at night (most of them as scheduled tasks). Over time the list of batch processes has further grown, with 85 processes running almost every night today. A sad record... Our business has further evolved and were it originally made sense to schedule all this work outside the regular business hours, we now encounter the following issues: The list of remaining free time slots is getting smaller and smaller, making it almost impossible to schedule a new task without interfering with other tasks. As our datasets have grown over the years, these processes typically also take longer and longer to execute. Our customers are interacting with our services more and more outside the regular business hours. It is no longer acceptable for our business to have to wait for some data. Realtime info is key to take correct business decisions. Some of these batch processes ar...

Generate Terraform configuration files from your Azure resources

While everyone is focusing all the announcements at Build 2025, I'm still processing some of the older recently announced features. A feature that I am happy that is finally available in preview is the Terraform export functionality in the Azure Portal. A similar feature already exists for some time for ARM and Bicep but now we can finally export to Terraform configuration files as well. Let’s give it a try… A short walkthrough Go to the Azure portal and browse to a specific resource. From there go to the Automation section and click on Export template . Click on the Terraform tab. The first time I did this I got the error below:   The reason is that you first need to register the Microsoft.AzureTerraform resource provider at the subscription level. Go to your Subscription in Azure. There open the list of Resource Providers .   Search for Microsoft.AzureTerraform resource provider and click on Register .   It can take some ...

The (non) sense of organization charts

Today while explaining my son how our heating system works, it brought me back to my earlier post about organization charts. Same as in heating system where you have a heating loop and a control loop, 2 loops exist in every organization. The first is formal and visible—it's drawn out in neat boxes and lines as your organizational chart, showing who reports to whom and where decisions get made. The second is informal and largely invisible—it's the actual pathways through which information, ideas, and real work flow to get things done. The two flows of organizational systems When we apply systems thinking to organizations, we can identify two critical flows that determine how effectively an organization functions: Control flow represents the formal authority structure—who has decision-making power, who approves what, and how accountability flows up and down the hierarchy. This is what your org chart captures beautifully with its clean boxes and reporting lines. Informat...

.NET 9–OpenAPI and Scalar–Adding custom headers

In this post I continue my investigation of using Scalar as an alternative to Swashbuckle that I was using before to expose my OpenAPI metadata in a userfriendly way. If you have no idea what Scalar is, I would recommend to check out my introduction post first before you continue reading. Today I want to have a look at how we can transform the OpenAPI metadata. On this specific API, it is expected that one of a set of custom headers is passed when calling the API. To simplify the experience, I originally created  an IOperationFilter for Swashbuckle to show these extra headers: How to customize the OpenAPI metadata in .NET 9? The generated OpenAPI document can be customized using “transformers”, which can operate on the entire document, on operations, or on schemas. Transformers are classes that implement the IOpenApiDocumentTransformer , IOpenApiOperationTransformer , or IOpenApiSchemaTransformer interfaces. Each of these interfaces has a single async method that receives...