Follow me on Twitter, happy to take your suggestions on topics or improvements /Chris
This article covers your first steps using .NET Core, the cross-platform version of .NET. We will be creating a solution, a library, a console app and also a test project. Of course, we will be taught how to execute our tests, all this from the terminal
.NET has been around since 2001 and a lot of developers have cut their teeth on using Visual Basic .NET or C# with Visual Studio. They were using Windows at the time. Times have changed, cross-platform is a must nowadays and .NET as well as Visual Studio exists on both Windows, Linux, and Mac.
In this article we will cover:
- Installing .NET Core and some nice extensions like C#
- Scaffold a solution
- Add a class library and add it to the solution
- Add a test project and run our tests
- Add a Console program and use our library
- Improve our IDE with vscode-solution-explorer extension
what commands we were taught and what to look at next like ASP, Docker, Cloud
Resources
Host a .NET Core app
There are many ways to host a .NET Core app, Windows, Azure etc.Publish you .NET Core app to the Cloud
Let's learn how to publish our .NET Core app to the Cloud and Azure.Sign up for a free Azure account
To be able to use Azure you will need a free Azure accountHello world tutorial - console app
This shows a simple Hello World console applicationContainerize a .NET Core App
This explains how to Dockerize your app, how to author the Dockerfile etc.Unit testing in .NET Core
There is more than one choice for unit testingdotnet CLI - all commands
There are so many commands for thedotnet
tool. Did you know that you can scaffold a .NET project with a React frontend for example?Create a new web app with ASP and .NET Core
Great tutorial for creating your first Web app in .NET Core
Install and Set up
The first thing you want to do is to install .NET Core. Head over to this page:
Once it's installed you should have access to a command-line tool you can invoke in the terminal called dotnet
. You can easily see what commands are available by typing:
dotnet --help
Quite a few commands as you can see above. We will explore some of these commands for creating solutions and projects.
Because we will be working with C# and VS Code I recommend downloading VS Code
Once you got VS Code on your system go and install the C# extension. Type C#
, it should look like so:
Good, now we are set up and ready code :)
Creating a solution
The first we will do is to create a solution. A solution is something we use to keep track of all related projects. As an old .NET developer you might be used to do this via Visual Studio but we will actually do this via the terminal.
We will take the following steps:
- Create a directory for our solution
- Invoke the command generating a solution
First things first, let's create a directory:
mkdir app
cd app
You can name your directory anything you want, app
was just an example.
Next, let's create a solution. We do this with the following command:
dotnet new sln
sln
is short for solution
, this will generate a new solution. Because we are standing in the app
directory this generates an app.sln
file.
Create a library
Next up we will generate a library. Now a library is not an executable program but more a set of files we include in other projects.
To create a library we will need to type the following in the terminal (we are still in the app
directory):
dotnet new classlib -o library
Above we can see that our general command is dotnet new
, followed by the type, which in this case is classlib
, then we use the flag -o
and the last argument is the name of the project.
Let's have a look at what we got:
We see that the directory library
was created. We also see that we got the file Class1.cs
, the project file library.csproj
and a directory obj
. At this point, lets switch to VS Code and look at our files. Looking att Class1.cs
, it looks like this:
// Class1.cs
using System;
namespace library
{
public class Class1
{
}
}
It doesn't do much but it's valid C# code.
Let's finish this section by adding to the solution:
dotnet sln add library/library.csproj
This adds the following entry to app.sln
:
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "library", "library\library.csproj", "{7F30581E-9BCD-46FB-B7A5-FC2A85DE1429}"
For now, we are not going to spend so much time thinking about this other than we have a solution that knows about our library.
Updating our library
Ok, we need to add some code to our library project. We will do the following:
- Download a NuGet package from a NuGet repository
- Reference our NuGet package in our library code
- Build our code
Download and use a package from the NuGet repository
Is a big (160k + libraries) repository where all NuGet libraries live. Anything that lives here can be downloaded by a simple command. For this part, we will grab a specific library called Newtonsoft.Json
. This will allow us to parse JSON back and forth. To make this library part of our solution we can type:
dotnet add library package Newtonsoft.Json
The above means we are adding the package Newtonsoft.Json
to the project library
. The command should be read like this:
dotnet add [what project to add it to] package [name of package at nuget.org]
Sometimes you might be working on an existing project or you might have grabbed the latest changes. Regardless of which, you might be missing some packages that your project or solution needs to run properly. At that point, you can run the command
dotnet restore
This will grab the packages specified as package references in your projects csproj
file.
Update our library code
In your library project, change the file Class1.cs
to Thing.cs
and add the following code to it:
// Thing.cs
using static Newtonsoft.Json.JsonConvert;
namespace Library
{
public class Thing
{
public int Get(int left, int right) =>
DeserializeObject<int>($"{left + right}");
}
}
Build
Next up we need to compile our code. This will, if successful, generate a so-called .dll
file. This is the format used by .NET for libraries and stands for dynamic link library.
So let's compile our code with the command:
dotnet build
As indicated in the above image, we get a library.dll
Success!
Creating a test library
Next up we will create a test project. All codes deserve some level of testing and what better way to start than having tests set up early on. To create a test project we need to type the following:
dotnet new xunit -o test-library
This will create a test project of type xunit
with the name test-library
.
Adding references
Let's add our project to the solution file as well:
dotnet sln add test-library/test-library.csproj
The idea here is to test functionality found in our project called library
. For this to be possible we need to add a reference to library
in our test-library
project, like so:
dotnet add test-library/test-library.csproj reference library/library.csproj
Writing a test
When we created our test-library
we got a file called UnitTest1.cs
created as well. Let's have a look at this file:
//UnitTest.cs
using System;
using Xunit;
namespace test_library
{
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}
}
We use the decorator [Fact]
to indicate that this is a test method that needs to be evaluated and ran. Let's add some code next to UnitTest.cs
:
//UnitTest.cs
using Library;
using Xunit;
namespace TestApp
{
public class LibraryTests
{
[Fact]
public void TestThing() {
Assert.NotEqual(42, new Thing().Get(19, 23));
}
}
}
Running our test/s
We are now ready to run our test and inspect the outcome.
To run the tests, type:
dotnet test test-library/test-library.csproj
We use the command dotnet test
and the last argument is where to find the project file for the test project. So what do we get?
We can see from the above image that our test run failed. It clearly indicated [Fail]
. Let's look at the WHY. Expected the result to be NOT 42. Hmm, let's check the implementation in Thing.cs
in our library
project:
public int Get(int left, int right) =>
DeserializeObject<int>($"{left + right}");
We cleary just take 2
input arguments and sum them up. What about the test in UnitTest1.cs
?
public void TestThing()
{
Assert.NotEqual(42, new Thing().Get(19, 23));
}
19
+ 23
to be NOT equal to 42. Wait a minute... It should be Equal
. Let's change that:
public void TestThing()
{
Assert.Equal(42, new Thing().Get(19, 23));
}
and let's rerun the test:
dotnet test test-library/test-library.csproj
Let's inspect the results and....
This time around the tests is succeeding.
Success! :)
Console app
Next thing we are going to do is to create a Console App. Why do you ask? Well, we want to show the whole idea of creating a reusable library that we can drop in anywhere, from test projects to console projects.
Let's generate our console project like so:
dotnet new console -o console-app
This gives us a runnable project with a file Program.cs
that serves as the entry point. Technically the entry point is a method called Main()
:
// Program.cs
using System;
namespace console_app
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
Let's add this project to the solution file, like so:
dotnet sln add console-app/console-app.csproj
Adding and using our library project
Next order of business is to start using our library
project and make it part of our console-app
project. So we add the dependency like so:
dotnet add console-app/console-app.csproj reference library/library.csproj
Read the above as:
dotnet add [target project] reference [destination project]
Next up we need to change the code of our Program.cs
file to the following:
// Program.cs
using System;
using Library;
namespace console_app
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"The answer is {new Thing().Get(19, 23)}");
}
}
}
Let's run the app next
dotnet run -p console-app/console-app.csproj
We got ourselves a running app, using the code from the library
project.
Awesome :)
Debugging
Debugging. That's one of the great things about using Visual Studio. It was and is outstanding. Personally, I think it's second to none, so what's the situation in VS Code?
Well, let's see how we debug and then reflect on how well it does it.
Now VS Code will ask you for adding a needed resource for debugging if you open a solution missing it. So how do I know what's missing? Well you should have a .vscode
directory looking like this:
That's it?
Well, you might try to select Debug/Start Debugging
from the menu and you will notice it's running the test-library
if you look at the end of the debug window
Now, you probably want to change that to actually run the console-app
project when debugging. To make that happen we need to go into launch.json
under the directory .vscode
. Find the entry looking something like this:
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/test-library/bin/Debug/netcoreapp2.2/test-library.dll",
"args": [],
"cwd": "${workspaceFolder}/test-library",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
}
We need to change the property "program"
to point to our console app and also the "cwd"
.
It should now look like the below in launch.json
Then select menu option Debugging/Start Debugging
and we should see the below
There we have it, boys and girls, working debugging :)
So, the experience, well the first thing that happened was that I just noticed that when I changed the code in Program.cs
my breakpoint was not hit properly. This had an explanation. Looking at our entry in launch.json
we see there is a property "preLaunchTask": "build"
that points out a task that should run before our debug. This task resides in tasks.json
. Heading over to that file we noticed that it looked like this:
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/test-library/test-library.csproj"
],
"problemMatcher": "$tsc"
}
YES, you are correct we weren't building the correct project before running the debug again. The way to fix this was to either run
dotnet build
in the terminal OR, fix this task and have it point to our console-app
, like so:
If you were to debug again everything works. Now you know a little bit more how things work in VS Code.
If I were to have an opinion here I would like to have this abstracted away from me as a user. I'd rather want a plugin doing this for me. At this point, I wish for a solution explorer, like the one I have in Visual Studio.
Improve IDE
If you are like me with more 10+ years on the .NET platform, you are looking for ways to make this into Visual Studio as much as possible. You, of course, welcome new ways of doing things like using the terminal but it feels like you want a UI. Maybe I should use the actual Visual Studio then?
Well, there is a plugin that fixes this. It's called vscode-solution-explorer
. If you install it your project will suddenly look like this:
and right-clicking on a project will give you a menu like this:
My spontaneous reaction is :)
This is not an official extension by Microsoft but it's very nice and well worth a try if you like me enjoy terminal commands but sometimes just want a UI.
Summary
Ok, let's try to sum this up. We have gotten quite the education on .NET Core. We were taught to use dotnet
core to do everything from scaffolding different types of project to creating solutions, adding references, building our code to running tests. Quite versatile.
Lastly, we also showed a plugin that offers an alternate approach to all our terminal commands. Of course, under the hood, it's running our terminal commands, so there is definitely value to learn the ways of the CLI. :)