NOTE : This post was initially written in early 2017 (!!!) but has now been completely revamped in 2020 to be up to date with .NET Core 3+ Watch feature. The original article was written in pre 1.0 days and is no longer relevant. But this is still a killer feature and should be used far more often!

One of the most overlooked features of .NET Core CLI is the “dotnet watch” command. With it, it allows you to have a “live reload” of your ASP.NET Core site running without having to either run the “dotnet run” command, or worse do the “Stop the process in Visual Studio. Write your changes. Recompile and run again” routine. The latter can be very annoying when all you are trying to do is do a simple one line fix.

If you are used to watches in other languages/tooling (Especially task runners like Gulp), then you will know how much of a boost watches are to productivity.

The Basics

I highly recommend creating a simple ASP.NET Core project to run through this tutorial with. The tooling can be a little finicky with large projects so it’s easier to get up and running with something small, then take what you’ve learned onto something a little larger.

For this demo, I have a simple controller that has a get method that returns a string value.

Open a command prompt in your project directory, a terminal in VS Code, or even the Package Manager Console in Visual Studio and run the following command :

Note that if you previously have had to run the “dotnet run” command with other flags (e.g. “dotnet run -f net451” to specify the framework), this will still work using the watch command. Essentially it’s saying “Do a watch, and when something changes, do ‘this’ thing” which in our case is the run command.  You should see something similar to the following :

This means you are up and running. If I go to http://localhost:5000/api/home, I should see my controller return “Old Value”.

Now I head back to my controller and I change the Get action to instead return “New Value”. As soon as I hit save on this file I see the following in my console window :

What we see is that the watch immediately exits, and it tells us that a file has been changed in HomeController.cs and so it starts recompiling immediately. When we browse to http://localhost:5000/api/home we see our “New Value” shown and we didn’t have to do anything else in terms of manually recompiling or running a new dotnet run command.

On larger projects, the recompile process can actually be a little slow so it’s not always an instant “change code and immediately refresh the browser” moment. Especially if you have a large dependency tree that means several projects need to be rebuilt before the site is back up and running. But it’s still going to be faster than whatever manual process you are used to.

Debugging With dotnet watch

So previously, debugging while using dotnet watch was almost a fruitless exercise. Each time your watch started and ran, a new “dotnet.exe” process would spin up. But the issue was it was impossible to find the “right” process to attach your debugger to. You might have a half dozen or so dotnet.exe processes running and you sort of had to wing it and pick the one that had been created most recent and hope for the best. Then each time you made a change, a *new* dotnet.exe would be spun up and your attached debugger was useless with you having to start the attach to debugger process all over again. Ugh!

As of .NET Core 3+, this is now much much easier.

Suppose I have my project up and running on a watch. In Visual Studio I simply go  Debug -> Attach To Debugger. I then filter all processes by the actual name of my project. In my case I called my project “WatchExample”, so I just start typing that into the filter box.

I click the Attach button and I’m away! Unfortunately each time you make a change the debugger is stopped while your project recompiles, but a helpful hint is to learn the “Reattach To Process” hotkey which in default Visual Studio key bindings is “Shift + Alt + P”. This immediately attaches the debugger to the last process it was on (Which in our case, is the our project exe), and we are away debugging again!

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

I’ve recently had the opportunity to start a Specflow/Selenium end to end testing project from scratch and my gosh it’s been fun. I’m one of those people that absolutely love unit tests and trying to “trick” the code with complicated scenarios. End to end testing with Selenium is like that but on steroids. Seeing the browser flash infront of you and motor through tests is an amazing feeling.

But in saying that. A key part of using Selenium is the “ChromeWebDriver”. It’s the tool that actually allows you to manipulate the Google Chrome browser through selenium. And let me tell you, there are a few headaches getting this set up that I really didn’t expect. Version errors, Not finding the right exe, Nuget packages that actually include the exe but it’s the wrong version or can’t be found. Ugh.

If you are not that big into automation testing, you can probably skip this whole post. But if you use Specflow/Selenium even semi-regularly, I highly recommend bookmarking this post because I’m 99% sure you will hit atleast one of these bugs when setting up a new testing project.

Chrome, Gecko  and IE Drivers

While the below is mostly about using ChromeDriver, some of this is also applicable for Gecko (Firefox), and IE drivers. Obviously the error messages will be slightly different, but it’s also highly likely you will run into very similar issues.

Adding ChromeDriver.exe To Your Project

The first thing to note is that you’ve probably added the “Selenium.WebDriver” and maybe “Specflow” nuget packages. These however *do not* contain the actual ChromeDriver executable. They only contain the C# code required to interact with the driver, but *not* the driver itself. It is incredibly confusing at first but kinda makes sense because you may want to only use Chrome or only Firefox or a combination etc. So it’s left up to you to actually add the required driver EXEs.

If you try and run your selenium tests without it, it will actually compile all fine and look like starting only to bomb out with :

Depending on your setup, it can also bomb out with :

So there are two ways to add ChromeDriver to your project. The first is that you can install a nuget package that will write it to your bin folder when building. The most common nuget package that does this is here : https://www.nuget.org/packages/Selenium.WebDriver.ChromeDriver/

But a quick note, as we will see below, this only works if everywhere you run the tests has the correct version of chrome that matches the driver. What?! You didn’t know that? That’s right. The version of ChromeDriver.exe will have a version like 79.0.1.1 that will typically only be able to run on machines that have chrome version 79 installed. The nuget package itself is typically marked with the version of Chrome you need, so it’s easy to figure out, but can still be a big pain in the butt to get going.

So with that in mind, the other option is to actually download the driver yourself from the chromium downloads page : https://chromedriver.chromium.org/downloads

You need to then drop the exe into your project. And make sure it’s set to copy if newer for your build. Then when building, it should show up in your bin folder. Personally, I found the manual download of the chromium driver to be handy when working in an enterprise environment where the version of chrome might be locked down by some group policy, or you are working with others who may have wildly different versions of chrome and you can do funky things like have different versions for different developers.

Passing The ChromeDriver Location

So you’ve downloaded ChromeDriver and when you build, you can see it in your bin folder, but everything is still blowing up with the same error, what gives?!

One of the more irritating things I found is that in so many tutorials, they new’d up a chromedriver instance like so :

Now this may have worked in .NET Framework (I haven’t tried), but atleast for me in .NET Core, this never works. I think there must be something inside the constructor of ChromeDriver that looks up where it’s current executable is running (e.g. where the Bin folder is), and in .NET Core this must be different from Full Framework.

In anycase, you can change the constructor to instead take the folder location where it can find the driver. In my case I want that to be the bin folder :

Obviously you can go ahead and change the path to anything which is super handy for differing dev setups. For example you could ask each dev to maintain their own version of chromedriver.exe somewhere on their C:\ drive, and then just pass that location into the constructor. Meaning that each developer can have a completely different version of chrome, and things will still run perfectly fine.

Versions Matter

We kinda touched on it above, but versions of ChromeDriver have to match the actual version of Chrome on the machine. If you are getting errors like so :

Then you have a mismatch between versions.

The easiest way to rectify the issue is to manually download the correct version of ChromeDriver from here : https://chromedriver.chromium.org/downloads and force your code to use it. If you are using a nuget package for the driver, then it’s highly likely you would need to switch away from it to a manual setup to give you better control over versioning.

Azure Devops (And Others) Have ChromeDriver Environment Variables

This is one that I really wish I knew about sooner. When I tried to run my Selenium tests on Azure Devops, I was getting version issues where the version of Chrome on my hosted build agent was just slightly different from the one on my machine. I tried to do all sorts of crazy things by swapping our the exe version etc, but then I found buried in a help doc that there is actually an environment variable named ChromeWebDriver that has the full path to a chromedriver that is guaranteed to match that of the chrome browser on the agent. So I wrote some quick code that if I was running inside Azure Devops, to grab that environment variable and pass that into my ChromeDriver constructor.

Again, this is only for Azure Devops. But if you are using Gitlab, Bamboo, TeamCity, whatever! Check to see if there is an environment variable on hosted agents that carries the location of ChromeDriver.

If you are using your own build agents, then it’s also a good idea to think about following the same pattern. It’s super handy to have the Build Agent look after it’s own versions rather than wrangling something in code to fudge it all.

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

In a previous post we looked at how we can publish a single exe from a .NET Core project. Now in it, I talk about how the resulting binary is absolutely massive, 70MB for a simple hello world console app! But I also talked about how there are now ways to significantly chop that down.

Despite that, when shared with Reddit, there was some comments that weren’t so impressed. Most notably this gem :

But that’s cool. For Scellow and anyone else that wasn’t impressed with the size of the exe, let’s look at how we can chop it down.

You Need .NET Core 3.0 (Preview 6+)

Like all these features I’m writing about recently, you’re gonna need the very latest version of .NET Core 3.0. At the time of writing it’s Preview 6. Any version earlier will simply not fly. And again, if that isn’t you and you don’t want to muck around with preview versions, then you’ll just have to wait!

PublishedTrimmed Flag

Before we go on, you might hear IL Linker talked about a lot. Possibly because it’s in the title of this post! But that’s because IL Linker is essentially the backbone of this entire feature. However where previous it was this external tool you had to grab from a nuget feed, now it’s built directly into .NET Core 3.0+ which is pretty impressive!

Anyway we previously published our application using the following command :

And with that, we ended up with an exe over 70MB big :

Not good. But literally all we have to do is add one flag and we can chop it down a bit :

So… 29MB. And this is about the time where you go “but shouldn’t this be KB in size?”. And honestly the answer is yes. It should be. But we have to remember that this is still a completely self contained application that doesn’t even require the target machine to know what .NET Core is. So even if we aren’t using things like say.. cryptography so we can get rid of that, there is probably a lot of basic and primitive .NET Core features that we just can’t get rid of.

Still. It’s an exe half the size with no functional difference between the two.

Reflected Assemblies

Through various forms of reflection, we may end up loading assemblies at runtime that aren’t direct references. Take this (very convoluted) example of loading an assembly at runtime :

Now when debugging this locally, and we have .NET Core installed, we ask for System.Security and it knows what that is because we are using the installed .NET Core platform. So running it, we get :

But if we publish this using the PublishTrimmed flag from the command line, then run it :

Unsurprisingly, we have trimmed a bit too much off. Because I don’t actually reference System.Security anywhere, it’s decided we aren’t actually using it. But there is a way to specify that we know best, and to package it up for us.

All we need to do is edit our csproj file for our project and add :

Now we will bundle up System.Security with our single exe and everything will run smooth! Pretty nice I have to say!

You may ask yourself “Well how will I know when I need to do this?”. Frankly 99% of the time you won’t. If you decide to trim your exe, you will need to really give it a good test before letting it out into the wild.

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

Say I have a simple “Hello World” console application that I want to send to a friend to run. The friend doesn’t have .NET Core installed so I know I need to build a self contained application for him. Easy, I just run the following command in my project directory :

Pretty self explanatory :

  • Publish the project from the current directory
  • Build the project to run on Windows 64 bit machines
  • Build in release configuration mode
  • Publish everything as “self-contained” so that everything required to run the app is packaged up with our executable

So this works right, we end up with a folder that has our exe and everything that is required to run it, but the issue is that there is a tonne required to run even a HelloWorld console app.

All up it’s a little over 200 files. Crazy – but it makes sense. It’s essentially having to package the .NET Core runtime just to run Hello World.

So functionally, this works. But optics wise, it looks like a mess. I’ve sent folders like this to clients and had to say “uhh.. So I’m going to send you a folder with hundreds of files in it… But… Can you just find the one titled MyApplication.exe and run that and don’t worry about the rest?”. When people are used to having an icon on their desktop they double click and things just.. work… This just doesn’t cut it.

You Need .NET Core 3.0 (Preview 5+)

I need to put that in bold because this will not work if you don’t have .NET Core 3.0. And if you are an early adopter (At the time of this post .NET Core 3.0 is not GA yet), you will need atleast preview 5 upwards. If you’re not one to mess around in preview’s, then you can just wait a few months till .NET Core 3.0 is released!

The PublishSingleFile Flag

All that intro and it literally comes down to a single command flag :

All this does is runs our publish command but tells it to package it within a single file. You’ll notice that we no longer specify the self-contained flag. That’s because it’s assumed that if you are packaging as a single exe, that you will want all it’s dependencies along with it. Makes sense.

And the output :

A single tidy exe! When this is executed, the dependencies are extracted to a temporary directory and then everything is ran from there. It’s essentially a zip of our previous publish folder! I’ve had a few plays around with it and honestly, it just works. There is nothing more to say about it. It just works.

Helpful Tip : Make sure you clean your publish directory or just outright delete your bin folder. It doesn’t break anything to not do so, but all those old DLL’s just hang around until you do so your nice single EXE is hard to spot. 

File Size And Startup Cost

Keen eyes will notice something about the above screenshot. The file size. It’s over 70MB! That’s crazy for an application that does nothing but print Hello World to the screen! This is solved in Preview 6 of .NET Core 3.0 with a feature called IL Linker or Publish trimmer that omits DLL’s that aren’t used. You can read more about that here!

The other issue you may find is that there is a slight startup cost when running the self contained executable for the first time. Because it needs to essentially unzip all dependencies to a temporary directory on first run, that’s going to take a little bit of time to complete. It’s not crazy (5 seconds or so), but it’s noticeable. Luckily on subsequent runs it uses this already unzipped temp folder and so startup is immediate.

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

I’ve previously done posts on how to setup both .NET Core 2.1 and .NET Core 2.2. The reason for these posts was because it was still a little shaky exactly which version of the SDK you needed to actually build for these platforms. e.x. If you had .NET Core SDK 2.1, it didn’t actually mean you could build .NET Core 2.1 projects (How infuriating is that?!).

But things have gotten better and now it’s usually just a matter of installing the latest SDK and away you go, so there isn’t really much I could normally write for each version bump. However! .NET Core 3 includes a couple of really important updates that I want to talk about in the future. Windows Forms/WPF development on top of .NET Core, and C# 8. Because of this, I wanted to have a post all written up on setting up your machine for .NET Core 3 development while things are in preview so I don’t have to repeat myself every future post!

Installing the .NET Core 3 Preview SDK

Installing the .NET Core 3 SDK is fairly straight forward. Just head to the download page and grab the SDK (Not the runtime) and install! You do want to ensure you are on the .NET Core 3 page and not the general download page of .NET Core as the current “live” version is 2.2 not 3.

Once installed, you should be able to open a command prompt and run  dotnet --info with the output being something close to :

Of course as long as the version is 3+, you should be good to go.

It’s also important to note that your default SDK on your machine will now be 3 and not 2.2 (Or the previous version you had installed). If you have existing projects that are using this SDK version, you will need to create a new global.json file to be able to run different SDK’s side by side. Luckily there is a great guide on how to do this right here!

Using VS Code

If you like programming in VS Code, then you’re actually good to write .NET Core 3 code right from the get go (Since it’s just a text editor). Obviously you will want to install the “C#” extension if you want all the good intellisense (Including for C# 8 new types), but other than that because builds are all from the command line there isn’t too much to it.

If you want to use C# 8 features in VS Code, see that section of this article below (It’s the same for Visual Studio or VS Code).

Using Visual Studio

A preview version of .NET Core also has a preview version of Visual Studio to accompany it. This can be a little annoying because it’s not just jumping on the “preview” update track for your existing Visual Studio installation, you actually need to download and install a completely new version of Visual Studio. This means another ~6GB of space taken up with a VS version you may use once or twice to try out new features.

I feel the need to point this out because it caught me out initially. The first version of Visual Studio to support .NET Core 3.0 is Visual Studio 2019 Preview 1. Emphasise on the 2019 part because I was wondering why my 2017 preview Visual Studio wasn’t working at first!

You can grab the preview version of Visual Studio here : https://visualstudio.microsoft.com/vs/preview/

I have actually dabbled with a solo installation of the preview version only and not bothered with the current release version. Theoretically it could have a few more bugs in it than the current supported release, but so far so good!

Enabling C# 8 Features

We can enable C# 8 on a project by project basis by editing our .csproj files. Simply open up your project file, and add the following anywhere within your <Project> node :

And that’s literally it (Too easy!).

Some people get trapped thinking that the following will enable C# 8 features :

But remember, version 8 of the language is in preview too. Latest refers to the latest minor version that has actually been released (So at this time, 7.3). If you try and use new features of C# 8, for example the “Range” type, you will get an error like so :

error CS8370: Feature ‘range operator’ is not available in C# 7.3. Please use language version 8.0 or greater.

But other than that, everything is pretty straight forward! Now go ahead and start using Range, AsyncEnumerable, Indices and Nullable Reference Types!

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

Recently while upgrading a couple of projects to .NET Core 2.2, I came across this error.

A quick google revealed that actually people had the same issue when their projects were going from 2.0 to 2.1 too. And all the fixes seemed kinda flaky and typically involved “Try this and pray” type steps.

To be honest, I know how to fix diagnose and fix the issue, but I don’t really know why that particular error message is the one that comes up.

First thing I noticed is that this error will only ever happen when you’ve tried opening a project in Visual Studio and tried to build. In some cases I’ve been able to build using the dotnet CLI, but not inside Visual Studio. If after building in Visual Studio, I then try and build from the dotnet CLI tool, I then start getting this error too. However if I delete the bin folder and rebuild from the CLI, we are all clear.

Next, in all cases the version of .NET Core I want to target is not available and not selected for my project inside VS. So if I right click my project and view properties, the Target Framework is blank :

This is because the version of Visual Studio that I’m using doesn’t actually support the version of .NET Core I am trying to run. It’s sort of this weird situation where even if you have the correct .NET Core SDK installed, that really only sets you up for using the dotnet CLI and writing code in something like VSCode.

All you need to do is update Visual Studio. Let me put that in big bold letters so people coming from Google can get their answer fast :

You Need To Update Visual Studio

Hopefully that’s clear enough!

Even once you update Visual Studio, you will likely need to delete the bin and obj folders of your project and then rebuild again from VS. Now there may be one very edge case that this doesn’t resolve your issues. And that’s if you are using the very latest preview builds for .NET Core SDK that Visual Studio either doesn’t support yet, or only supports in the Pre-Release version of VS. Rare, but it does happen.

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

There is some pretty nifty stuff making it’s way into .NET Core 2.2 such as a new route “dispatcher” and inbuilt support for healthchecks. But you’re going to need to set up your workstation (And your project) to handle .NET Core 2.2 first! In previous articles where we’ve updated from 2.0 to 2.1, it’s been a right headache, but slowly Microsoft are getting better at handling this whole version bump thing.

If You Want Preview – Use The Command Line

Just to kick us off, I need to point out that in almost all cases, if you are intending to use the preview SDK’s for .NET Core. You are going to need to be creating, building, and publishing projects from the command line. There is support for Visual Studio for preview SDK’s in some cases, but even opening a preview project in the wrong version of Visual Studio can completely break the project by dumping junk in the bin folder etc.

So again, try and do all of the following without Visual Studio atleast so you know it works. Then you can deal with the headache of Visual Studio!

Installing The .NET Core 2.2 SDK

So remember that there is really two parts to .NET Core. There is the SDK which is how your project is built, and the runtime which is what your application actually runs on.

Let’s first sort out the SDK part of this equation.

We want to go to specifically the .NET Core 2.2 download page and download the latest SDK (Not runtime) for our operating system. Note that this isn’t the general .NET Core download page, the current LTS version of .NET Core is currently 2.1. So that’s the version that gets thrust upon you. You specifically need to skip that, go direct to the 2.2 download page, and install the latest SDK.

After installing, open a command prompt and run the following :

This tells us what it thinks the latest (Or to be more correct, the default) version of the .NET Core SDK we are running.

In this example, I’m currently running version 2.2.100-preview3, which is the latest at the time of writing. Anything 2.2.*** should be fine. It’s also interesting to note that this is a big departure from .NET Core 2.1, where you could have version 2.1.*** of the SDK, and it actually couldn’t build 2.1 projects… So it’s nice Microsoft have tidied that up.

Now if you create a new project using the command line, by default it’s going to be using 2.2 as it’s SDK, but if you want to modify an existing project to use the latest build tools (And remember, the SDK is different to the runtime as we will see later), then you need to modify your global.json.

In the root of your project, you should either already have a global.json or create a new one. The contents of which should look like :

Where the version should match your SDK you just installed.

Without a global.json, you will actually use the default anyway. But it’s good to try and be explicit with what version of the SDK you know everything builds fine with. This is especially true if later you install a new version of the SDK with breaking changes, and all your old projects “automatically” update and break.

Updating A Project Runtime To .NET Core 2.2

Changing the project runtime is actually super easy. Just open up your csproj and bump up your TargetFramework.

Go ahead and build your project using dotnet build  from the command line, and all going well you should be good to go.

If you see an error such as :

Then you currently aren’t running on the latest SDK. Either you have not installed the latest SDK or your global.json in the project/solution folder is pointing to an older version.

Visual Studio Support

.NET Core 2.2 does have support inside Visual Studio but only from version 15.9 Preview 3 onwards. At the time of writing, this means you need to download the pre-release version of Visual Studio here to get access to that specific version.

The installation itself is some 5GB, so unless you really need the full development experience for preview SDK’s, you should probably try and go without!

If you are able to upgrade non pre-release version of Visual Studio to atleast 15.9, then you should be able to open .NET Core 2.2 projects.

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

There is some pretty nifty new features making their way into .NET Core 2.1, many of which I’ll be blogging about in the near future. One of the not so nifty features is actually being able to target .NET Core 2.1. There is one or two headaches along the way that’s for sure.

Installing And Targeting .NET Core 2.1 SDK

Remember that .NET Core comes in two “parts” as it were. The “SDK” which is essentially the thing that does the “building” of your application, and the actual runtime which does the… running… of the application. The versions of these don’t always match up, but generally speaking when we are talking about .NET Core 2.1, we are talking about a specific version of the runtime. The versions might not always line up because there might be improvements to the “build” tools that don’t actually need a version bump of the runtime. This has caused a real stupid overlap of the versions as we will soon see…

Head over to the “all downloads” page and grab the latest SDK. It’s super important to download the latest SDK from this page, and not from the .NET Core homepage. The one on the homepage is the latest “stable” version that may not support 2.1 (Atleast it doesn’t at the time of writing).  The SDK also comes with the runtime that is vaguely matching (e.g. if you download the latest SDK, you’ll get the latest runtime). Because the version numbers don’t always line up, mostly be looking for the final screen that should atleast tell you you’ve installed a 2.1.0 runtime :

Once installed, from a command prompt run : dotnet --list-sdks . Which should in turn print something like :

Don’t worry about earlier versions for the most part. Just make sure the last one is the one you just installed (It should be!). I just want to point out a major headache at this point. You’ll notice I have three versions of SDKs above 2.1.* And an interesting point about that is that only 2.1.300 actually supports building 2.1. If you try and build using the SDK version 2.1.105, it says it cannot build .NET Core 2.1 projects. Now I know that the versions won’t always line up… But it’s a hell of an annoyance.

Now in the root of your solution you want to “.NET Core 2.1-ify”. You want to add a global.json file to the solution folder or edit the existing one there. Inside this file, the contents should be similar to :

Where version is the very latest .NET Core SDK you downloaded. This actually becomes pretty important when you upgrade because you may have projects you want to use the “old” tooling. I actually already wrote a pretty indepth article on working with two different versions of an SDK side by side here. So if you want to know more about this global.json file does, head over there.

You can run dotnet --version  in your solution directory which will print out the SDK version it’s about to run. If all looks good (e.g. it’s the latest SDK version that you just installed), enter dotnet build . All going well it will build your project!

OK that’s cool, but so far we are just building a .NET Core 2.0 projects with a 2.1 SDK. So let’s change that.

Targeting Core 2.1 Runtime

Targeting the 2.1 runtime is as easy as opening up your projects .csproj file. And changing the TargetFramework tag.

Head to your command prompt and run dotnet build  in your solution directory again. Everything should build fine. If instead you get :

C:\Program Files\dotnet\sdk\2.1.105\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.TargetFrameworkInference.targets(135,5): error : The current .NET SDK does not support targeting .NET Core 2.1.

Then it is *highly* likely you are building with the wrong SDK. The most likely scenario that I’ve found is that you’ve downloaded a “2.1 SDK” that doesn’t actually build 2.1 projects… As stupid as that sounds. Remember, the first SDK to actually be able to build 2.1 projects is 2.1.300-preview2-008533 . Anything earlier and it’s not gonna happen. The first part of the error actually tells you which SDK you are attempting to use, so make sure it’s the right one.

If you are a command line/notepad/VSCode kinda guy, then you should be all ready to go at this point. If you prefer using Visual Studio, read on!

Dealing With Visual Studio Messiness…

Now the interesting thing about using .NET Core 2.1 in Visual Studio is that VS kind of has it’s own way of doing things sometimes. And you’ll notice that if you open your project in Visual Studio you’ll be prompted with a message like so :

Visual Stdio 2017 version 15.7 or newer is recommended for .NET Core 2.1 projects.

To be honest, I tried playing around with a few of the .NET Core 2.1 specific features and I couldn’t find anything that would outright break inside Visual Studio. But better safe than sorry!

When you want to update Visual Studio, you would typically go Help -> Check for Updates and pick up the update there. In this case you would be (sort of) wrong. At the time of writing Visual Studio version 15.7 is only available as a “preview” download and not as a regular update. If you are already on the latest update of the stable builds, you just get told that you’re all good and you can go away now.

Instead, inside Visual Studio go to Tools -> Get Tools and Features. You’ll be presented with a bunch of workloads that you can change in a sort of popup, instead hit the “X” up the top right of this window. On this screen you are left with, scroll right down to the bottom and select to install the “Preview” Visual Studio Version.

Unfortunately this installs an entirely new version of Visual Studio on your PC. Complete with taking up 5.65GB of your precious SSD space.

For this reason, you may want to wait a bit until these things make it into the regular stream (Or play solely with preview stuff in something like VS Code). I’m a sucker for punishment so I did install it and can confirm the annoying warning message when opening .NET Core 2.1 projects does go away.

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

In a previous post I talked about building cross platform GUI applications using Eto.Forms. One thing that came up was that to run the applications on Linux, you needed to have Mono installed and to run mono with the executable as an input argument. That’s probably fine if you are building a web application and it’s going to be on limited servers, but if you are distributing a desktop application you may not want to have to guide a user into downloading and using mono themselves.

Luckily, there is actually a way of bundling mono with your application that removes the need for a user to have to download, install, and then run mono. This means you can distribute your application to a Linux machine without any worry about prerequisites.Now I know this isn’t really .NET Core, but one of the most important things about Core is the cross platform-ness. And since Core doesn’t have desktop application support, I may aswell write a little bit on how to make that happen using Mono.

Setup and Install

The craziest thing about looking up how to use Mkbundle on Windows is that there is very little information about it in the past 5 years. Everything I found was from 2013 or earlier, and it was very outdated. It often involved downloading Cygwin and fiddling with paths and environment variables until things just sort of fell into place. To be fair, there comes a time in every Windows developers life when they resign themselves to the fact they will have to install Cygwin for whatever flaky piece of software they need to use, but today is not that day!

Head over to the Mono website and download the latest version for your PC : https://www.mono-project.com/download/stable/

I personally went with the 32 bit, just because everything I read out there was using that version and I didn’t want to run into an issue that “needed” the 32 bit version after all.


This part is important so I’ve put it in bold and put it between horizontal rules just to make sure you read this part! 

After install comes an extremely important step. This might sound like a little side bar but please, if this is your first time trying mkbundle on Windows, you will thank me later. If you try and run MKBundle right away, you will get an error that likely looks like this :

ERROR: The SDK location does not contain a C:\Program Files (x86)\Mono/bin/mono runtime

I smacked my head against the wall for an age with this. Eventually I actually tracked down the source code for mkbundle on Github. And found this line here : https://github.com/mono/mono/blob/master/mcs/tools/mkbundle/mkbundle.cs#L536

What it’s trying to do is check that you have a *file* called “C:\Program Files (x86)\mono\bin\mono”. Now I bold that part about it being a file, because it’s not looking for a directory. On non Windows systems, files don’t need to have extensions (like .exe), but on Windows they typically do. So what we actually need to do is make sure that this “test” passes. And it’s simple. Go to your mono/bin folder. In there, you should find a mono.exe. Make a *copy* of this file, and remove the extension so it is simply called “mono”. And it should sit side by side with your existing exe.

Now this should satisfy the file check and mono should run fine. I have logged a ticket on Github with Mono around this issue here : https://github.com/mono/mono/issues/7731 . So if you have the same problem or you’re coming from Google after smacking your head against the desk repeatedly with this issue, jump on and add your 2 cents!


Fetching The Correct Mono Runtime

OK with that out of the way, after installing everything you should now have a “Mono Command Prompt” available to you on your machine. Just type “Mono” in your start menu and it should pop up!

This works essentially like a regular command prompt, with the Mono commands already built in.

Now the next step is a little tricky. It’s not like you can run mkbundle and suddenly you have an executable for every OS in existence. Instead you need to fetch the runtime for the particular OS you want your application to run on, and bundle it for that particular runtime. If we package an exe with mkbundle right now then the only people that can run that application are people with the same OS (In our case Windows). This is not as dumb as you might first think. If we did do this, it would mean we could distribute an application that could run on Windows without Mono (Obviously), but more importantly without .NET Framework. There is definitely times where this could come in handy, but for now, we want to build for Linux, so let’s do that.

There is supposed to be commands to fetch and download various runtimes to your machine right from the command prompt. Ofcourse, Mono being a flaky POS at times (Sorry, it’s getting irritating working through these issues), the command doesn’t work at all. Instead if we run the command that “should” fetch available runtimes we get :

System.Net.WebException: Error: TrustFailure (The authentication or decryption has failed.)

And if instead we try the command that supposedly will download the runtime we want (For example we know the runtime signature so just slam that in), we will get :

Failure to download the specified runtime from https://download.mono-project.com/runtimes/raw/

So, we have to do everything manually.

First go to this URL : https://download.mono-project.com/runtimes/raw/. You need download the runtime for the particular OS you want to compile to. Once downloaded, you need to extract this to a particular directory in your documents folder. If I downloaded mono 5.10.0 for Ubuntu, then my directory that I extract to should be :  C:\Users\myuser\Documents\.mono\targets\mono-5.10.0-ubuntu-16.04-x64/ .

Once this has been done, we should then be able to run a command within the mono command prompt :  mkbundle --local-targets . The output of this should be all “targets” we have available to us.

mkbundle Command

Navigate to your applications directory that you want to “bundle”. In my case I’ve created a simple “HelloWorldConsole” application that does nothing but print out “Hello Mono World”. Inside this directory I run the following command  mkbundle HelloWorldConsole.exe --simple -o HelloWorldBundleUbuntu --cross mono-5.10.0-ubuntu-16.04-x64  Where HelloWorldConsole.exe is my built console app, the -o flag is what I want the output filename to be, and the –cross flag tells us which runtime we want to compile for.

Looks good to me! But let’s test it. Just for comparison sake, I also run the following command :  mkbundle HelloWorldConsole.exe --simple -o HelloWorldBundleDefault . This will give us a bundled application but it will be using our default mono runtime (Which in this case is Windows). This will be important later for showing the differences.

Just quickly, I also want to show the size difference between our original application, and our bundled app.

 

So in terms of bundling, using Windows mono we add about 4mb. For the Ubuntu bundle, we added 8mb. Your guess is as good as mine when it comes to why the huge size difference, but the main thing is that adding 4 – 8mb actually isn’t that bad when you consider a user now doesn’t have to worry about download mono themselves. That’s actually a relatively small bundle when you think about other assets that may be going along with the app like sound, sprites, images etc.

Let’s go ahead and copy these two bundles to our Ubuntu machine for testing.

First we will take a look at our default bundle. Now this shouldn’t work at all because it’s been built for Windows. We even have a command that we can use to check the file type. So let’s try that.

So straight away it’s telling us this is for Windows. And when we run it…

Yep, so it ain’t happening. Let’s instead try our Ubuntu bundle. First the file command to see if it recognizes that it’s a different sort of application :

So even though under the hood it’s actually the exact same C# executable, it’s been compiled correctly for Ubuntu. And when we run it :

Yes! We did it! It only took me a day of headaches to work out every little issue with mkbundle to get a HelloWorld bundle working on Ubuntu! But we did it!

Final Notes

One final thing I want to say is Mono/mkbundle is pretty crap to work with on Windows. I know there is definitely going to be someone out there that hates me for saying that, but it truly is. Some of these issues that I ran into (Notably the fact it tries to check for an extension-less mono exe when running mkbundle) I can see stackoverflow questions from over a year ago having the exact same problem. That means that these problems are nothing new.

Even the documentation was rife with issues on Windows. Simply put, they didn’t work. In some ways I can understand that Mono is built for non Windows machines in mind, but it is shockingly bad for a product that Microsoft has now taken under it’s wing.

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

This article is part of a series on setting up a private nuget server. See below for links to other articles in the series.

Part 1 : Intro & Server Setup
Part 2 : Developing Nuget Packages
Part 3 : Building & Pushing Packages To Your Nuget Feed


Packaging up your nuget package and pushing it to your feed is surprisingly simple. The actual push may vary depending on whether you are using a hosted service such as MyGet/VSTS or using your own server. If you’ve gone with a third party service then it may pay to read into documentation because there may be additional security requirements when adding to your feed. Let’s get started!

Packaging

If you have gone with building your library in .NET Standard (Which you should), then the entire packaging process comes down to a single command. Inside your project folder, run  dotnet pack and that’s it! The pack command will restore package dependencies, build your project, and package it into a .nupkg.

You should see something along the lines of the following :

While in the previous article in this series, we talked about managing the version of your nuget package through a props file, you can actually override this version number on the command line. It looks a bit like this  :

I’m not a huge fan of this as it means the version will be managed by your build system which can sometimes be a bit hard to wrangle, but it’s definitely an option if you prefer it.

An issue I ran into early was that many tutorials talk about using nuget.exe from the command line to package things up. The dotnet pack command is actually supposed to run the same nuget command under the hood, but I continually got the following exception :

After a quick google it seemed like I wasn’t the only one with this issue. Switching to the dotnet pack command seemed to resolve it.

Publishing

Publishing might depend on whether you ended up going with a third party hosted nuget service or the official nuget server. A third party service might have it’s own way of publishing packages to a feed (All the way to manually uploading them), but many will still allow the ability to do a “nuget push” command.

The push command looks like the following :

Again this command is supposed to map directly to the underlying nuget.exe command (And it actually worked for me), but it’s better to just use the dotnet command instead.

If you are using a build server like VSTS, Team City, or Jenkins, they likely have a step for publishing a nuget package that means you don’t have to worry about the format of the push command.

Working With VSTS

For my actual nuget server, I ended up going with Microsoft VSTS as the company I am working with already had their builds/releases and source control using this service. At first i was kinda apprehensive because other VSTS services I’ve used in the past have been pretty half assed. So color me completely surprised when their package hosting service was super easy to use and had some really nifty features.

Once a feed has been created in VSTS, publishing to it is as easy as selecting it from a drop down list in your build.

After publishing packages, you can then set them to be prerelease or general release too. In a small dev shop this may seem overkill, but in large distributed teams being able to manage this release process in a more granular way is pretty nifty.

You can even unlist packages (So that they can’t be seen in the feed, but they aren’t completely deleted) see a complete history of publishes to the feed, and how many times the package has been downloaded. Without sounding like a complete shill, Microsoft definitely got this addon right.

Summary

So that’s it. From setting up the server (Or hosted service as it turned out), developing the packages (Including wrangling version numbers), and putting everything together with our build server, it’s been surprisingly easy to get a nuget server up and running. If you’ve followed along and setup your own server, or you’ve already got one up and running (Possibly on a third party service), drop a comment and let me know how it’s working out!

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.