Authoring Templates
|
This section documents MSBuild 18.9, the .NET SDK 10.0.402 (with its This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The C# Reference bibliography lists the reference material consulted while preparing these pages. |
A dotnet new template is an ordinary, buildable project (or set of files) plus a .template.config/template.json
that tells the template engine what to rename, which options to offer and what to do afterwards. Because the source is
a working project, the template is tested by building it. This page extends Ledgerline's ledgerline-app template
with .NET SDK 10.0.402. Using templates is on
dotnet new and Templates; packing and
publishing the template package is on
Tool and Template Packages.
Structure
src/Ledgerline.Templates/
Ledgerline.Templates.csproj the packaging project (PackageType=Template)
templates/
ledgerline-app/ one template: a working console project
.template.config/
template.json the template definition
LedgerlineApp.csproj "LedgerlineApp" is replaced by the user's -n name
Program.cs
journal.csv optional content
Each folder that contains a .template.config is one template; a package can hold many.
template.json
{
"$schema": "http://json.schemastore.org/template",
"author": "Ledgerline contributors",
"classifications": [ "Console", "Accounting" ],
"identity": "Ledgerline.Templates.App",
"name": "Ledgerline console app",
"shortName": "ledgerline-app",
"sourceName": "LedgerlineApp",
"preferNameDirectory": true,
"tags": { "language": "C#", "type": "project" },
"symbols": {
"Framework": {
"type": "parameter",
"datatype": "choice",
"choices": [ { "choice": "net10.0" }, { "choice": "net8.0" } ],
"defaultValue": "net10.0",
"replaces": "net10.0",
"description": "The target framework."
},
"IncludeSample": {
"type": "parameter",
"datatype": "bool",
"defaultValue": "true",
"description": "Add a sample journal.csv and print its trial balance."
}
},
"sources": [
{
"modifiers": [
{ "condition": "(!IncludeSample)", "exclude": [ "journal.csv" ] }
]
}
],
"primaryOutputs": [ { "path": "LedgerlineApp.csproj" } ],
"postActions": [
{
"description": "Restore NuGet packages required by this project.",
"manualInstructions": [ { "text": "Run 'dotnet restore'" } ],
"actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025",
"continueOnError": true
}
]
}
| Key | Meaning |
|---|---|
|
Unique, stable ID of the template (not shown to users). |
|
Display name, and the name typed after |
|
Text replaced everywhere — file names and content — by the |
|
Create a folder named after |
|
Shown in |
|
Options. A |
|
Include, exclude or rename files under a condition. |
|
The files post actions operate on. |
|
Steps after creation; |
Conditional content
Inside source files, the template engine processes #if (Symbol) / #else / #endif — in C# they look like
preprocessor directives, so the template source still compiles:
using Ledgerline;
#if (IncludeSample)
var path = args.Length > 0 ? args[0] : "journal.csv";
#else
var path = args[0];
#endif
var lines = LedgerReader.ReadFile(path);
Console.WriteLine(Ledger.ToJson(Ledger.TrialBalance(lines)));
Whole files are included or excluded with sources.modifiers, as journal.csv is above.
Source: Custom templates for dotnet new.
Testing from the folder
During development, install the template from its folder — no package needed — and instantiate it both ways:
dotnet new install ~/ledgerline/src/Ledgerline.Templates/templates/ledgerline-app
dotnet new ledgerline-app -h
dotnet new ledgerline-app -n Shop
dotnet new ledgerline-app -n Bare --IncludeSample false
Success: ~/ledgerline/src/Ledgerline.Templates/templates/ledgerline-app installed the following templates:
Template Name Short Name Language Tags
---------------------- -------------- -------- ------------------
Ledgerline console app ledgerline-app [C#] Console/Accounting
Template options:
-F, --Framework <net10.0|net8.0> The target framework.
Type: choice
net10.0
net8.0
Default: net10.0
-I, --IncludeSample Add a sample journal.csv and print its trial balance.
Type: bool
Default: true
The template "Ledgerline console app" was created successfully.
Processing post-creation actions...
Restoring ~/try/Shop/Shop.csproj:
Determining projects to restore...
Restored ~/try/Shop/Shop.csproj (in 381 ms).
Restore succeeded.
The template "Ledgerline console app" was created successfully.
The results:
-
Shop/heldShop.csproj,Program.csandjournal.csv; itsProgram.cskept the#if (IncludeSample)branch, anddotnet runprinted the sample’s trial balance. -
Bare/held onlyBare.csprojandProgram.cs, withvar path = args[0];— the#elsebranch, and no journal.
The short options (-F, -I) were generated from the symbol names. dotnet new uninstall <folder> removes a
folder-installed template. Template creation can run the restore and other actions, so — as the documentation warns — install templates only from sources you trust.
Localization
The name, description and symbol texts can be translated with one file per culture in
.template.config/localize/templatestrings.<culture>.json (for example templatestrings.de.json). dotnet new and
Visual Studio show the strings for the current UI culture. The templatepack project template from
Microsoft.TemplateEngine.Authoring.Templates generates a packaging project with template validation and localization
tasks already wired in.
Common mistakes
-
A
sourceNamethat also appears in unrelated text — every occurrence is replaced. -
Changing
identitybetween versions — users end up with two templates. -
Template source that does not build — build it in CI like any other project.
-
Relying on the restore post action in CI — restore explicitly; the action can be skipped (
--no-restore).