Reimagine dotnet-new (dotnet new enhanchements 2)
See original GitHub issueAs it currently stands, dotnet new
is a good command for people to get started with simple projects. However, it suffers from several things:
- Templates are coupled with the implementation, thus requiring a new release of the CLI when adding/changing templates
- Extending templates is tough
- No support for naming projects via the command line
This issue suggests a new form of dotnet new
that solves the above problems. It also replaces the old dotnet/sdk#4695 that will be closed in favor of this one.
/cc @DamianEdwards @piotrpMSFT @Eilon @enricosada
.NET Core CLI: new
The new
command is used to create new .NET Core projects. Projects are created using templates installed via NuGet packages.
Templates are laid out in their NuGet packages in a hierarchical fashion that enables the creation of simple trees of templates
with categories that are then merged across the installed template packages to create an overall template tree. This tree allows
the display of an interactive menu when creating new projects, while also allowing for direct project creation using a template
node’s full path, e.g. dotnet new -t aspnetcore/mvc/empty
As templates are in normal NuGet packages and installed into the standard NuGet packages folder, they can depend on other NuGet packages that are used in their templates, such that when they’re installed, all the required packages to create new projects using the contained templates are installed too.
Using the Command Line
Displaying help:
~/code> dotnet new --help
Usage:
dotnet new
dotnet new -t|--template <template/path> [-n|--name <ProjectName>] [[-v|--variable <Name> <Value>] [-v|--variable <Name> <Value>]]
dotnet new <arguments>
Arguments:
-t|--template <template/path> The path of the template to use
-n|--name <ProjectName> The name of the new project, created in current folder if not specified
-v|--variable <Name> <Value> Variable to be passed to the template (can be specified more than once)
-l|--list Lists installed templates
-i|--install <TemplatePackageId> [version] Installs templates from a package with optional version
-i|--install <TemplatePackagePath> Installs templates from a package
-u|--uninstall <TemplatePackageId> Uninstalls a templates package
-r|--restore Restores installed template packages
Listing installed templates:
~/code> dotnet new --list
MS.DotNetCore.New.Templates 1.0.0
- Console Application [console]
- Class Library [classlib]
~/code>
Installing new templates from a package:
~/code> dotnet new --install MS.DotNetCore.New.Templates.AspNetCore 1.0.0
Installing templates from MS.DotNetCore.New.Templates.AspNetCore
Installed 3 templates:
- ASP.NET Core Empty Application [aspnetcore/empty]
- ASP.NET Core MVC Web Site [aspnetcore/mvc/website]
- ASP.NET Core MVC Web API Application [aspnetcore/mvc/webapi]
~/code> dotnet new --list
MS.DotNetCore.New.Templates 1.0.0
- Console Application [console]
- Class Library [classlib]
MS.DotNetCore.New.Templates.AspNetCore 1.0.0
- ASP.NET Core Empty Application [aspnetcore/empty]
- ASP.NET Core MVC Web Site [aspnetcore/mvc/website]
- ASP.NET Core MVC Web API Application [aspnetcore/mvc/webapi]
~/code>
Creating a new project with a specific template:
~/code> mkdir MyApp && cd MyApp
~/code/MyApp> dotnet new --template console
Created project "MyApp" in ~/code/MyApp
~/code/MyApp> cd ../
~/code> dotnet new -t console --name MyApp2
Created project "MyApp2" in ~/code/MyApp2
~/code> dotnet new -t aspnetcore/mvc/website --name MyWebApp
Created project "MyWebApp" in ~/code/MyWebApp
~/code>
Creating a new project using the template menu:
~/code> dotnet new
Templates
-----------------------------------
1. Console Application [console]
2. Class Library [classlib]
3. ASP.NET Core [aspnetcore]
Select a template [1]: 1
Enter a project name [Project1]: MyApp
Created project "MyApp" in ~/code/MyApp
~/code/MyApp> cd../
~/code> dotnet new
Templates
-----------------------------------
1. Console Application [console]
2. Class Library [classlib]
3. ASP.NET Core [aspnetcore]
Select a template [1]: 3
ASP.NET Core Templates
-----------------------------------
1. ASP.NET Core Empty Application [aspnetcore/empty]
2. ASP.NET Core MVC [aspnetcore/mvc]
Select an ASP.NET Core template [1]: 2
ASP.NET Core MVC Templates
-----------------------------------
1. ASP.NET Core MVC Empty [aspnetcore/mvc/empty]
2. ASP.NET Core MVC Web Site [aspnetcore/mvc/website]
3. ASP.NET Core MVC Web API Application [aspnetcore/mvc/webapi]
Select an ASP.NET Core MVC template [1]: 2
Enter a project name [Project1]: MyWebApp
Created "MyWebApp" in ~/code/MyWebApp
~/code/MyWebApp>
Authoring Templates
Templates are placed in NuGet packages in the content/templates
folder. Optionally, in the root of the folder is a templates.json
file
that describes the templates contained and if present is used to enhance the project creation experience.
The layout allows for multi-level category nodes with template nodes as the leaves. In the case a category node contains just a single template node, that template will be automatically selected when the category is chosen.
Example templates.json
Example templates.json
for the default templates:
{
"projectTemplates": {
"console": {
"title": "Console Application",
"children": {
"csharp": {
"title": "Console Application (C#)",
"variables": {
"framework": {
"question": "Please select a target framework",
"default": "netstandardapp1.5",
"conditions": {
"rid": ["win7"]
}
}
}
}
}
},
"classlib": {
"title": "Class Library",
"children": {
"csharp": {
"title": "Class Library (C#)",
"variables": {
"framework": {
"question": "Please select a target framework",
"default": "netstandardapp1.5",
"conditions": {
"rid": ["win7"]
}
}
}
}
}
}
}
}
Package Files Layout
The following demonstrates the layout of template NuGet packages. Note how templates from separate packages can share their structure such that they’re templates can occupy the same parts of the resultant installed template “tree”.
~/.nuget/
packages/
Microsoft.NETCore.New.Templates/
templates/
templates.json
console/
csharp/
files/
Program.cs
classlib/
csharp/
files/
project.json
Program.cs
Microsoft.NETCore.New.Templates.VB/
templates/
templates.json
console/
vb/
files/
project.json
Program.vb
classlib/
vb/
files/
projext.json
Program.vb
Microsoft.NETCore.New.Templates.AspNetCore/
templates/
templates.json
aspnetcore/
empty/
csharp/
files/
project.json
Program.cs
mvc/
empty/
csharp/
files/
project.json
Program.cs
Startup.cs
Controllers/
HomeController.cs
wwwroot/
website/
csharp/
webapi/
csharp/
Issue Analytics
- State:
- Created 7 years ago
- Reactions:12
- Comments:35 (25 by maintainers)
Thoughts on command line project creation
With
dotnew new
we are interested in enabling an experience for users to create new projects from the command line. Creating projects from the command line is not a new concept, it’s been around for a while especially on the web development side. One example of a successful command line project generator isyeoman
. Yeoman is a super popular tool for developers, and ifdotnet new
is as successful as yeoman, IMO, that would be a really wonderful thing. To enable a meaningful discussion ondotnet new
let’s start by taking a look at a typical user experience when usingyeoman
to create a new project. Below are typical steps a user would take to create a new project from the command line.Steps to create a new project from yeoman
From the set of steps above, we can break this down into the following categories.
I think that
dotnet new
should focus on the overall end user experience. Which consists of the following,Template discovery
andCommand line interaction
. When the user selects and invokes a template,dotnet new
will handle prompting for project properties and then call the generator (with a consistent way to pass project properties). The template should be able to use any “template generator” that it desires.dotnet new
will have a template generator available out of the box which can be used. For scenarios in which the default template generator doesn’t meet the needs, it can always be switched out for a different implementation.In my case I work on delivering templates in the following areas.
yo aspnet
dotnet new
(future)Today for VS and
yo aspnet
we have to author templates once for VS and once foryo aspnet
. In addition the template infrastructure that we use for the VS side is very fragile and difficult to maintain. Once we enable templates indotnet new
it’s yet another place for us to invest in creating templates. Instead of maintaining three different templates I’d like to have one way to create templates from the command line, and then reuse that tool everywhere. So we author templates once indotnet new
which enables the command line experience withdotnet new
. Then in Visual Studio we create “shim templates” which will allow us to present the UI to gather parameters and then call intodotnet new
for the project creation process. Foryo aspnet
we would do a similar thing.Ideas for implementation
Brokers are decoupled from specific generators via a set of C# interfaces. This will allow us to maximize reusability of generators in different scenarios including; command line, Visual Studio, yeoman, etc.
Here is a typical user session when creating a new project and a high level of what happens.
Setup
When
dotnet-new
or Visual Studio are installed the following happens.Users can add additional sources to enable using additional generators.
Project Creation
X
)X
X
and stops when a match is found (or some other heuristic to find the single generator to use)FAQ
Q: Does this mean
yo aspnet
will go away?A: Absolutely not.
yo aspnet
has had some wonderful success it’s not going anywhere. The idea is that we will create a self-contained template tool and then plug that into: VS,dotnet new
,yo aspnet
, etc. By allowing us to author templates once it will allow us to bring a better experience inyo aspnet
. And it will enable us to keep templates in sync at all times across all end-user experiences.Q: Why not just use yeoman here?
A: Yeoman has a lot of dependencies which are required to use it. It makes sense to have an entry point in yeoman because many people already have it installed (or some of it’s dependencies). There are drawbacks from shipping/using yeoman directly by Visual Studio include the following.
About other languages support ( just to check my use case ):
--list
should output all templates installed,--list --lang f#
only the templates who support f#--list --lang vb
should show grouped templates ( likeaspnetcore
) if at least one of aspnetcore subtemplates support vb (let’s filter out useless groups, but i’d like aspnet to support f# 😄 )That’s useful not only for people who use only one language, but for poliglot who have multiple languages installed (i use c# and f#, both a lot)
Now the bonus points (suggestions) for a better cross language experience. The c# is the default language, np about that, there is
--lang
and it’s ok (was already discussed and it’s ok). But i think we can improve experience for others without changing c# experience:dotnet-new
for example an env varDOTNET_DEFAULT_LANGUAGE
(see https://github.com/dotnet/cli/issues/1118#issuecomment-188790061 )--list
write name of supported languages near template name