dotnet new Feature Selection

In my last post I showed how to get started with using dotnet new to build project templates. In this post, I’m going to build on that knowledge and show how to add feature selection to your project template so developers can choose to add or remove bits of your template. If you check out my Boilerplate API project template, you’ll see that I have 17 features for you to set. If you run the help command against my template you’ll see a description of each and instructions on how you can set them (I’ve cleaned up the CLI output, the current help commands output is pretty awful but this is being addressed in the next version of dotnet new).

As you can see from the output, there are a few different types of feature you can create. You can also choose to make a feature required or optional. An optional feature, if not specified by the user will fall-back to a default value. Here are the different types available:

  • bool – This feature can be turned on or off and has a default of true or false.
  • string – This can be used to do a string replacement in your template. It has a default value which you can set to any arbitrary value.
  • choice – This is a feature with two or more named choices. Each choice can have it’s own description. The default value must be one of the choices.
  • computed – These are features flags that can be computed based on other symbols.

Bool Symbols

You can create a boolean feature by adding symbols section to your template.json file. If you look at the example below, I’ve specified an optional bool symbol, with a default value of true.

In your code, you can then use the symbol name, in this case ‘Swagger’ as a pre-processor directive in C# code:

This is really cool because you can still run the application as a template author and the project will still work. If you define a ‘Swagger’ constant in your project properties, your feature will turn on or off too. This makes debugging your project template very easy as a template author.
If you want to use the symbol in files other than C# where pre-processor directives do not exist, you can use the comment syntax specific to that file extension, so in a JavaScript file would use the ‘//’ syntax:

Most file extensions that have their own comment syntax have been catered for. For text files where there is no comment syntax or for any file extension that the templating engine doesn’t know about you can use the ‘#’ character:

You can look at this code in the templating engine for a full list of supported file extensions and comment types.

String Symbols

String symbols can be used to do simple file replace operations.

The above symbol looks for a ‘PROJECT-TITLE’ string and replaces it with whatever the user specifies or with the default value ‘Default Project Title’ if the user doesn’t set anything.

Choice Symbols

A choice symbol is useful when you have more than two options and can’t use bool.

In the example above, you have the choice of selecting a target framework, with a value of .NET Core, .NET Framework or Both. Each choice has it’s own description and the overall symbol also has it’s description.

Computed Symbols

In the above example, you can’t use the value ‘.NET Core’ as a C# pre-processor variable because it contains a dot and a space. This is where a computed symbol comes in handy.

Here I have set up two computed symbols which determines whether ‘.NET Core’ or ‘.NET Framework’ was selected individually in the previous choice symbol. I have named these symbols without a dot or space i.e. ‘NETCore’ and ‘NETFramework’ so I can use these as C# pre-processor symbols, the same way I showed above.

Conditionally Deleting Files or Folders

You can also use symbols to delete certain files or folders. In this example, I’ve extended my bool symbol example to additionally remove two files and a folder if the feature is deselected by the user.

You do this by adding source modifiers. I’ve added one here with a condition and three file and folder exclusions. The exclusions use a globbing pattern.

What’s Next?

There are several other useful features of the templating engine which I’ll cover in a follow up post as this is starting to get quite long. Feel free to take a look at the source code for my API template to see a full example.