When I search for something, I typically start with pmichaels.net [tab] [search term] – especially if I know I’ve come across a problem before. This post is one such problem: it’s not hard to find the solution, but it is hard to find the solution on this site (because until now, it wasn’t here).
The error (which is also in the title):
IConfiguration does not contain a definition for GetValue
Typically appears when you’re using IConfiguration outside of an Asp.Net Core app. In fact, GetValue is an extension method, so the solution is to simply add the following package:
Some time ago I wrote this post on creating a message on the Service Bus. However, with .Net Core comes a new way of doing things. In fact, the new method has a lot to be said for it; but it is very different.
If you’ve had a peek at the link above, you’ll see it’s festooned with screenshots – there’ll be a lot fewer in this post, as I’ll be using the Azure CLI. You can install this separately, but once you’ve done so, I heartily recommend downloading the Windows Terminal.
To log-in to the Azure CLI, simply type:
In Powershell (ideally using Windows Terminal, but if you choose to use a Powershell console then… well, there’s just no talking to some people!)
Create a Namespace and Resource Group (or vice-versa)
As with the previous post, we’ll need a namespace to use Service Bus; let’s create one is the CLI:
az servicebus namespace create --resource-group MyResourceGroup --name MyFunkyNS --location ukwest
So, MyResourceGroup is a resource group; you can create this in the Portal, or use the following command:
az group create -l ukwest -n MyResourceGroup
This will create the resource group in the location (-l) of ukwest and will be named (-n) MyResourceGroup. ukwest happens to be the closest location to me. At the time of writing, my figures are showing that you’re almost three time more likely to be from the USA than the UK and twice as likely to be from India if you’re reading this. You should definitely not pick ukwest if you’re not from the UK.
At any time, you can see what you’re doing (or at least the results of what you’re doing) by just loading the portal, but creating resources this way means that they can go into a script.
Now that you’ve created the namespace, you’ll need a connection string: you can get this using the following command:
az servicebus namespace authorization-rule keys list --resource-group MyResourceGroup --namespace-name
MyFunkyNS --name RootManageSharedAccessKey --query primaryConnectionString --output tsv
This should give you the connection string.
Creating the Queue
In the above linked post, creating the queue in code was trivial – there was simply a method on the library that allowed you to create a queue. Whilst convenient, this was possibly misplaced; the management of the namespace has now been moved to a separate library. For the purpose of this post, we’ll just create the queue using the CLI:
az servicebus queue create --resource-group MyResourceGroup --namespace-name MyFunkyNS --name MyQueue
This gives you a queue, so now we can write some code to create a message.
Writing to the Queue
Your first step is to install the library Microsoft.Azure.ServiceBus:
The code looks like this:
var queueClient = new QueueClient(ConnectionString, "MyQueue"); // ConnectionString is taken from above - just above the title 'Creating the Queue'
var message = new Message(Encoding.UTF8.GetBytes(messageBody));
What’s really good is that there is now a Service Bus Explorer, which means you can look at the messages:
At first glance, the new library seems more complex than the old Framework library; but when you delve into it, it actually makes much more sense. I’ll try to cover the management API in a future post.
In this post I covered how to debug a failing build. This is more of the same, really; a sort of hodgepodge of bits that have cropped up while discovering issues with various projects.
If you’re interested, the library that caused all this was this one.
Let’s start with the version number that you’re building for. When you create the initial build you get a targetted .net version; and by default, it’s very specific (and the latest version):
There’s two things that are worth noting here. The first is that if you intend to release this library on NuGet or somewhere else that it can be consumed, then the lower the target version, the better. A .Net Core app can consume a library of the same version or lower. This sounds obvious, but it’s not without cost: some of the GitHub actions depend on later versions. For example, Publish Nuget uses the switch —skip-duplicate, which is a .Net 3.1 thing. If you try to use this targeting a previous version of .Net, you’ll get the following error:
error: Unrecognized option '--skip-duplicate'
The second thing of note is the specific version; it’s not as well documented as it should be, but you can simply use something like this:
And you’re build will work with any version of 3.1.
Cross Platform, Verbosity and Tracing
As with the post mentioned above, I had an issue with a specific library, whereby two of the tests were failing. The first test in question called a line of code that compared two strings:
if (String.Compare(string1, string2, StringComparison.OrdinalIgnoreCase) == 0)
It turns out that this doesn’t work cross platform, and was failing because it was running on Ubuntu.
The second issue was slightly more nuanced, and relates to the dates (1/3 was being read as 3/1); this isn’t specifically a Linux / Windows issue, but it is something that’s different between testing on your local environment, and on the build server. This might not be as much of an issue if you’re in the U.S. (or any country that formats its dates with the month first).
Although I initially suspected the cause, I began by changing the log level on the build:
run: dotnet test --no-restore --verbosity normal
run: dotnet test --no-restore --verbosity detailed
Unfortunately, this didn’t really give me anything; and I’m sad to say that I next resorted to inserting lines line this into the code to try and determine what was going on:
I’m not saying this is the best method of debugging (especially in a situation like this), but it’s where we all go to when nothing else works.
A Better Way – Debugging on Linux Locally
In this post I covered how you can install Ubuntu and run it from your Windows Terminal, and in this post, I covered how you can install .Net on that instance. This means that we can run the tests directly from Linux and see what’s going on locally.
Simply cd to the directory that you’ve pulled the code down to, and run dotnet test. You may need to run it as elevated privilege, but it should run, and fail with the same error that you’re getting from GitHub:
I’ve used GitHub Actions a few times now, and this issue of the code running on a different platform is by far the most challenging thing about using them. Given that this is running on a Windows machine, being able to run (and debug) on a Linux platform is a huge step forward.
With the new Windows Subsystem for Linux, and the Windows Terminal, comes the ability to run .Net programs on Linux from your Windows machine.
Here I wrote briefly about how you can install and run Linux on your Windows machine. In this post, I’ll cover how to install .Net.
If you don’t have the Windows Terminal, then you can install it here.
The installation process is pretty straightforward, and the first step is to launch the Windows Terminal. Once that’s running, open a Linux tab, and run the following two scripts (if you’re interested in where these came from, follow the link in the References section below):
You’ll then need to turn on the subsystem. Launch Windows Features:
This requires a restart, in fact, this whole process requires at least two restarts. Once you’ve brought the machine back up, have a look on the Windows Store for your favourite Linux; here’s the Ubuntu one:
Once this has installed, launch the store app. You’ll be prompted to select a username and password – this is your root password, so make sure you know what it is.
Now launch Windows Terminal:
And you’re away – you can rm -r to your hearts content!