.NET Core has been around for a while (over three years if you count the release candidates). Over that time, the framework and tooling around it has evolved rapidly. I remember starting work on a new ASP.NET Core website back when the framework was in its first release candidate. At that time there was very little integrated tooling support and even less documentation. Confusion and growing pains aside, it’s now a technology that I would consider a must-have, due to its simplicity and flexibility.
One of the key features that comes with .NET Core is a robust Command Line Interface (CLI) that allows a user to create a multi-project solution with very minimal overhead. In addition, the commands supported work cross-platform so there isn’t a need to have to learn a new interface when switching between platforms. While there are many more awesome aspects of .NET Core, I’ll be focusing on the CLI. (See all our App Modernization capabilities)
A Battle of Interface Paradigms
CLI vs GUI. This is one of those epic programmer battles akin to Tabs vs Spaces. Many people prefer the user experience gains that you can get from a Graphic User Interface (GUI). It can be easier to discover features, and friendlier to look at (if done well). Batch processes can be hidden away behind magic walls (Visual Studio is great about doing this). However, that magic and beauty can be a double-edged sword. It can be painful to dig into some of the magic going on at times in an IDE. They also can take up a large amount of system resources.
In contrast, using a terminal to issue commands makes the user intimately aware of what they are doing (by design). The learning curve can be steeper, and there have been noted examples of mistakenly typed commands that have had disastrous impact. However, once you learn the commands necessary for the framework, you can work quickly. You can easily repeat commands, and you also don’t need to learn new commands when moving to different platforms.
In most cases, the debate comes down to personal taste. Some people like being able to issue commands and have the power that comes with the command line, and some prefer the more guided environment that a GUI offers. You can also utilize a terminal inside of most GUIs and get the benefits of both approaches.
.NET Core CLI
So, what can you do with the .NET Core CLI that you can’t do with Visual Studio?
Recent releases of Visual Studio have narrowed the gap and added in the functionality that the CLI provides (generally by using the CLI in the background). You can create and maintain .NET Core applications and libraries without ever needing to use the CLI. However, using the CLI decouples you from having to use Visual Studio. Depending on your machine and platform, this is a very good thing. It opens the door to using more streamlined applications to help develop your code (Visual Studio Code, Atom, Rider, Vim, Emacs), many of which are free to use. The CLI has commands that make editing and updating solution and project files simple (as we’ll soon see). You can also use the CLI to set up a variety of different project types in various languages.
If you want to try these out, make sure you have the .NET Core SDK installed. This can be easily checked by opening a terminal window and typing:
dotnet --version
You should see the version of the SDK installed. If not, you’ll want to download the .NET Core SDK. To discover other commands available, you can just type:
dotnet
Some of the more useful commands you will use are:
dotnet new
– Used to create new projectsdotnet run
– Used to run projectsdotnet test
– Used to execute test projects and run unit testsdotnet publish
– Used to publish projectsdotnet sln add/remove
– Used to add projects to a solution filedotnet add/remove reference
– Used to add project references to another projectdotnet add/remove package
– Used to add NuGet package references to a project
While there are more commands available, these will get you most of the way to creating, developing, and deploying a multi-project solution.
Example Multi-Project Solution
Let’s use these commands to create a very simple MVC-based web app that has a backing data store in a separate .NET Standard library. Open your terminal of choice and navigate to the directory that you want the solution folder to reside in. Once there, type the following command:
dotnet new sln -o MyWebApp
Note: If you are typing these commands by hand I recommend using TAB
to help with file name autocompletion.
The -o
parameter lets you specify the output directory (which will get created in case it doesn’t exist). Once that command finishes, navigate into the folder and then execute the following commands:
dotnet new mvc -o MyWebApp.Client
dotnet new classlib -o MyWebApp.DataStore
dotnet new mstest -o MyWebApp.DataStoreTest
dotnet sln MyWebApp.sln add .\MyWebApp.Client\MyWebApp.Client.csproj .\MyWebApp.DataStore\MyWebApp.DataStore.csproj .\MyWebApp.DataStoreTest\MyWebApp.DataStoreTest.csproj
dotnet add .\MyWebApp.Client\MyWebApp.Client.csproj reference .\MyWebApp.DataStore\MyWebApp.DataStore.csproj
dotnet add .\MyWebApp.DataStoreTest\MyWebApp.DataStoreTest.csproj reference .\MyWebApp.DataStore\MyWebApp.DataStore.csproj
These commands scaffold out the application for us. We first create 3 projects (an MVC web application, a C# library, and a Unit Test project). We then add the 3 projects to the solution file (we can add multiple projects to the solution in a single command by separating them with a space). Finally, we add the DataStore reference to both the WebApp and UnitTest projects.
We can now run the unit test project by the following command:
dotnet test .\MyWebApp.DataStoreTest\MyWebApp.DataStoreTest.csproj
And we can also run the web app by the following command:
dotnet run -p .\MyWebApp.Client\MyWebApp.Client.csproj
As you can see, we do have to specify the -p
flag to get the dotnet run
command to properly target the correct project. We could have also navigated directly to the project folder. In that case, we wouldn’t need to specify the project and just used dotnet run
.
Suppose we’ve developed our application and it’s now time to publish. We can easily do this straight from the command line via the following command:
dotnet publish .\MyWebApp.Client\MyWebApp.Client.csproj -o ..\build -c Release
This will publish the website out in release mode to a build folder in the root of your solution. You could also specify an absolute path to a folder (such as one that IIS watches).
.NET Core Templates
The example above was a very primitive solution compared to most projects, but it does touch on many of the core (no pun intended) features of the .NET Core CLI.
In addition to the three templates we used, there are many more that ship with the .NET Core SDK. You can easily spin up a boilerplate console application, Angular web app, and even dabble with F# and VB projects. The template system is quite flexible and can be extended to create custom templates that suit your organization.
There are also many third party templates you can use. The website https://dotnetnew.azurewebsites.net contains a consolidated list of some that have been published. Any of these projects can then be stitched together with the methods we explored above to create the type of tailored solution that your application requires.