Key Takeaways
- The .NET CLI includes a template engine, which can create new projects and project items directly from the command line. This is the “dotnet new” command.
- The default set of templates covers the essential project and file types you need for default console and ASP.NET-based apps, and test projects.
- Custom templates can create more interesting or bespoke projects and project items, and can be distributed and installed from NuGet packages or directly from the file system.
- Custom templates can be very simple or much more complex, with substitution variables, command-line parameters and conditional inclusion of files or even lines of code.
- Maintenance and testing of custom templates is easy, even with conditional code, by making sure a project template is always a runnable project.
This article is part of our .NET educational series which explores the benefits of the technology and how it can help not only traditional .NET developers but all technologists that need to bring robust, performant and economical solutions to market.
With the release of .NET Core 3.0, Microsoft has the next major version of the general purpose, modular, cross-platform and open source platform that was initially released in 2016. .NET Core was initially created to allow for the next generation of ASP.NET solutions but now drives and is the basis for many other scenarios including IoT, cloud and next generation mobile solutions. Version 3 adds a number of oft-requested features such as support for WinForms, WPF and Entity Framework 6.
The tooling story changed dramatically with .NET Core, because of its serious emphasis on the command line. This is a great fit for .NET Core’s cross-platform, tooling-agnostic image. The dotnet CLI is the entry point to all of this goodness, and it contains many different commands for creating, editing, building, and packaging .NET Core projects. Here, we’ll focus on just one aspect of the dotnet CLI — the dotnet new command.
This command is mainly used to create projects, and you can often create a simple boilerplate project and then forget about it. We’ll look at how to get the most out of this command, by passing arguments to modify the generated projects, and seeing how we can use the command to create files as well as projects. We’ll also see that this tool is a full-fledged template engine, and can be used to install custom templates, as well as make personal templates.
dotnet new in action
So how do you use dotnet new? Let’s start at the beginning and work up to the most interesting stuff. To create a simple console application, start up the command line, change directory to a new empty folder (an important step, explained below), and call dotnet new console:
> dotnet new console
The template "Console Application" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on /Users/matt/demo/MyNewApp/MyNewApp.csproj...
Restoring packages for /Users/matt/demo/MyNewApp/MyNewApp.csproj...
Generating MSBuild file /Users/matt/demo/MyNewApp/obj/MyNewApp.csproj.nuget.g.props.
Generating MSBuild file /Users/matt/demo/MyNewApp/obj/MyNewApp.csproj.nuget.g.targets.
Restore completed in 234.92 ms for /Users/matt/demo/MyNewApp/MyNewApp.csproj.
Restore succeeded.
As I mentioned before, make sure you’re in a new, empty folder first. By default, dotnet new will create files in the current folder and will not delete anything that’s already there. You can make it create a new folder by using the –output option. For example, you could create a project in a new folder called ConsoleApp42 by typing:
> dotnet new console --output ConsoleApp42
The template "Console Application" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on ConsoleApp42/ConsoleApp42.csproj...
Restoring packages for /Users/matt/demo/ConsoleApp42/ConsoleApp42.csproj...
Generating MSBuild file /Users/matt/demo/ConsoleApp42/obj/ConsoleApp42.csproj.nuget.g.props.
Generating MSBuild file /Users/matt/demo/ConsoleApp42/obj/ConsoleApp42.csproj.nuget.g.targets.
Restore completed in 309.99 ms for /Users/matt/demo/ConsoleApp42/ConsoleApp42.csproj.
Restore succeeded.
Looking at what you’ve created
At this point, dotnet new has created a new console project and restored NuGet packages — it’s all ready to run. But let’s take a look at what’s been created:
> ls ConsoleApp42/
ConsoleApp42.csproj Program.cs obj/
As you can see, you now have a project file based on the name of the output folder. If you wish, you could use the –name parameter to specify a different name:
dotnet new console --output ConsoleApp42 --name MyNewApp
This would create the project files in a folder called ConsoleApp42, and would use MyNewApp as the name of the console application being created — you’d get MyNewApp.csproj. If you take a look at Program.cs, you’ll also see that the name parameter is used to update the namespace:
using System;
namespace ConsoleApp42
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
Prepping for another project
But, if you take a look at the folder structure of the project you’ve just created, you might spot something missing — there’s no solution file. You’ve only got a single project, and while this works fine with dotnet run, it will cause problems when you want to add another project. You can easily create one:
dotnet new sln
This will create a new, empty solution file. Then, it’s another step to add a project to it.
If you created your solution in our demo’s root folder, it would look like:
dotnet sln add ConsoleApp42/MyApp.sln
You can also use the dotnet sln command to remove or list projects in a solution. If you want to add or remove references to a project, you need to use the dotnet add
command. I suggest reading Jeremy Miller’s article on the extensible dotnet CLI for more details, or type dotnet help sln or dotnet help add.
Adding another project is very easy also, but you must do it in this two-step fashion — create, then add. For example, you could add a test project to your solution:
dotnet new nunit --output Tests --name MyAppTests
dotnet sln add Tests/MyAppTests.csproj
Adding new files to a project
Adding new files to a project is even easier, mostly thanks to the improvements .NET Core made to MSBuild files. You no longer need to explicitly list C# files in the .csproj file, because they’re automatically picked up through wildcards. You just need to create a file in the folder and it will automatically become part of the project. You can create the file manually, but you can also use dotnet new to provide a template file. For example, you could add a test file to your test project using the nunit-test item template:
dotnet new nunit-test --output Tests --name MyNewTests
Speaking of templates, how do you know what templates are available? How can you tell the difference between a project template and an item template? That’s a job for dotnet new –list, which outputs a list of available templates:
Templates | Short Name | Language | Tags |
---|---|---|---|
Console Application | console | [C#], F#, VB | Common/Console |
Class library | classlib | [C#], F#, VB | Common/Library |
Unit Test Project | mstest | [C#], F#, VB | Test/MSTest |
NUnit 3 Test Project | nunit | [C#], F#, VB | Test/NUnit |
NUnit 3 Test Item | nunit-test | [C#], F#, VB | Test/NUnit |
xUnit Test Project | xunit | [C#], F#, VB | Test/xUnit |
Razor Page | page | [C#] | Web/ASP.NET |
MVC ViewImports | viewimports | [C#] | Web/ASP.NET |
MVC ViewStart | viewstart | [C#] | Web/ASP.NET |
ASP.NET Core Empty | web | [C#], F# | Web/Empty |
ASP.NET Core Web App (Model-View-Controller) | mvc | [C#], F# | Web/MVC |
ASP.NET Core Web App | razor | [C#] | Web/MVC/Razor Pages |
ASP.NET Core with Angular | angular | [C#] | Web/MVC/SPA |
ASP.NET Core with React.js | react | [C#] | Web/MVC/SPA |
ASP.NET Core with React.js and Redux | reactredux | [C#] | Web/MVC/SPA |
Razor Class Library | razorclasslib | [C#] | Web/Razor/Library/Razor Class Library |
ASP.NET Core Web API | webapi | [C#], F# | Web/WebAPI |
global.json file | globaljson | Config | |
NuGet Config | nugetconfig | Config | |
Web Config | webconfig | Config | |
Solution File | sln | Solution |
This lists all templates. You can use the –type parameter to filter this down, using –type project, –type item, or –type other. Project templates will create a project, item templates create a single file, while other is really only useful for the sln template to create a solution file.
The short name (2nd column above) in this list is the name you use in the call to dotnet new (e.g. dotnet new console, dotnet new classlib, dotnet new mvc, etc). Some templates support multiple languages, with the default shown in square brackets (spoiler — it’s always C#). You can choose a different language with the –language option, but be careful of the # symbol! Some command-line shells treat this as a comment character and parsing can fail with –language F#. This can be handled by quoting the value – “–language F#”.
Finally, each template has one or more tags. These are a way of classifying templates, but aren’t currently used as part of the command-line tooling. However, they could be used for grouping or filtering by other hosts. Yes, that’s right, the dotnet new template engine can be used in other hosts, such as IDEs. More on that later.