Template Packaging
This repository includes a dotnet new template scaffold and a NuGet template package project.
The scaffold can be installed locally from source for development, or packed into a .nupkg and installed through the same package-based flow expected for consumers.
Package-based validation is preferred because it verifies the actual distribution artifact instead of only the repository working tree.
Template Identity
| Field | Value |
|---|---|
| Template short name | netcoreapp-template |
| Current NuGet package ID | NetCoreApplicationTemplate |
| Previous NuGet package ID | CDCavell.NetCoreApplicationTemplate |
| Template identity | AsiBackbone.NetCoreApplicationTemplate.CSharp |
| Template group identity | AsiBackbone.NetCoreApplicationTemplate |
| Source replacement token | ProjectTemplate |
| Current package version | 2.11.1 |
The 2.0.0 release moved the public NuGet package ID to NetCoreApplicationTemplate. Release 2.8.0 aligns the internal template identity and group identity with the AsiBackbone organization namespace. The public package ID and template short name remain unchanged.
Consumer Scaffold Boundaries
The scaffolded output intentionally includes:
- Source projects under
src/. - Baseline tests under
tests/. - Checked-in
packages.lock.jsonfiles for every generated project. - The shared AsiBackbone
.editorconfigformatting and analyzer baseline. - Docker support files.
LICENSE.txt.ASSETS-LICENSES.md.- A consumer-oriented
README.mdgenerated from.template.content/README.md.
The repository-level ASSETS-LICENSES.md inventories package, documentation, NuGet icon, and generated-application assets. Generated projects receive .template.content/ASSETS-LICENSES.md, which retains the applicable package and application-favicon notices without referring to repository-only docs/images/ or PACKAGE-ICON.png paths. Update both inventories when generated dependencies change; update the repository inventory when repository or package image assets change.
The scaffolded output intentionally excludes repository-maintainer content such as:
.github/workflow and issue-template files..template.config/and.template.content/authoring files.- DocFX documentation source and ADRs.
- Changelog, citation, community, governance, contribution, security, and release-management files.
- Repository maintenance scripts and pre-generated SQL migration scripts.
- Repository maintainer badges and release instructions.
The scaffold does not ship a pre-generated SQL migration script. SQL is provider-specific and a checked-in generated artifact can become stale as migrations evolve. Consumers should generate and review a script from the migrations in their generated application for the target provider and deployment state.
Generated Formatting Baseline
The repository-root .editorconfig is the shared baseline ratified for AsiBackbone/AsiBackbone, AsiBackbone/Learning, and AsiBackbone/NetCoreApplicationTemplate. It is explicitly included by .template.config/template.json, packed into the template NuGet package, and required by the golden scaffold manifest. The scaffold validator verifies that the generated file matches the repository baseline exactly, including for all six supported authentication and database option combinations exercised by CI.
Generated applications receive this file as a consistent starting point and may customize it after generation to suit their own requirements. The baseline currently has no NetCoreApplicationTemplate-specific extensions. Any future repository-only exception must be clearly labeled, scoped to template-authoring paths that cannot match generated application content, and reviewed before the baseline is synchronized to sibling repositories.
Template Content Overlay
.template.content/ holds files that replace their src/ counterparts during scaffolding. An overlay file shadows the repository file entirely, so a setting added to src/ProjectTemplate.Web/appsettings.json and not to the overlay is absent from every generated project. Nothing fails when that happens: the overlay is still valid JSON, and the missing key falls back to its code default, so the drift is only visible by comparing the two files.
eng/Validate-TemplateContentOverlay.ps1 compares the JSON key structure of each overlay file against its src counterpart and fails when a key exists in one and not the other. Values are compared as well, except where the overlay holds a template token such as TemplateAuthEnabled, TemplateDataProvider, or TemplateDataConnectionStringName, since those are substituted during scaffolding and are expected to differ.
CI runs it on every build. Run it locally after changing either file:
./eng/Validate-TemplateContentOverlay.ps1
Overlay files with no src counterpart, such as nuget.config and README.md, are scaffold-specific by design and are skipped.
Golden Scaffold Manifest
The approved default scaffold surface is tracked in eng/scaffold-manifest.default.json.
The manifest is validated by eng/Validate-ScaffoldManifest.ps1 after CI packs the template package, installs the generated .nupkg, and scaffolds the default ContosoSecurityPortal project.
The manifest check fails when:
- An expected consumer file is missing.
- An expected consumer directory is missing.
- An unexpected root-level file is generated.
- The generated
.editorconfigdiffers from the shared repository baseline. - A maintainer-only path such as
.github/,.template.config/,.template.content/,docs/,eng/,scripts/,CHANGELOG.md,CITATION.cff,CONTRIBUTING.md,RELEASE.md, orSECURITY.mdappears in the scaffolded output. - The generated consumer README contains repository maintainer content such as workflow badges or the current-release block.
The manifest intentionally allows recursive content under src/ and tests/ because those folders are part of the consumer scaffold surface. Root-level additions should be added to expectedFiles only when they are intended public scaffold files.
Validate a Generated Scaffold Locally
After packing and installing the template package, generate the default scaffold:
dotnet new netcoreapp-template -n ContosoSecurityPortal --output ./artifacts/scaffold/ContosoSecurityPortal
Validate the scaffold against the checked-in manifest:
./eng/Validate-ScaffoldManifest.ps1 -ScaffoldRoot ./artifacts/scaffold/ContosoSecurityPortal
Intentionally Update the Manifest
When the public scaffold surface intentionally changes, regenerate the scaffold from the packed .nupkg, inspect the generated output, and then refresh the manifest:
./eng/Validate-ScaffoldManifest.ps1 -ScaffoldRoot ./artifacts/scaffold/ContosoSecurityPortal -Generate
Review the manifest diff carefully before committing. Changes to root-level files, maintainer-only exclusions, template source boundaries, README content checks, or public scaffold folders should be treated as release-surface changes.
Pack the Template Package
From the repository root:
dotnet pack ./eng/NetCoreApplicationTemplate.Template.csproj --configuration Release --output ./artifacts/template-package
Tagged releases generate an SPDX SBOM and a SHA-256 manifest from this exact .nupkg, publish GitHub build-provenance attestations, and attach the durable evidence to the corresponding GitHub Release. NuGet Trusted Publishing authenticates the protected workflow to NuGet.org but does not sign the package. NuGet author signing remains deferred under ADR-0005; the OCI image's Cosign signature is a separate control and does not cover the .nupkg.
See Container Release Publishing for the release asset contract and tested consumer verification commands.
Install the Template Package
Install the published package from NuGet:
dotnet new install NetCoreApplicationTemplate::2.11.1
Install a locally packed package:
dotnet new install ./artifacts/template-package/NetCoreApplicationTemplate.2.11.1.nupkg
Create a New Project from the Template
From a separate working directory:
dotnet new netcoreapp-template -n ContosoSecurityPortal
Use a project name that is also a valid C# identifier, such as ContosoSecurityPortal. Dotted project names require additional template symbol handling so namespace replacement and type-name replacement can be handled separately.
This creates a new project using ContosoSecurityPortal as the replacement name for the source template namespace and project prefix.
Template Options
The template intentionally exposes a small set of stable options for common scaffold variants.
| Option | Default | Supported values | Description |
|---|---|---|---|
--authProvider |
cookie |
cookie, none |
Selects the generated authentication baseline. Use cookie for the default cookie-authentication-ready baseline or none to generate the application with application authentication disabled by default. |
--dbProvider |
sqlite |
sqlite, sqlserver, none |
Selects the generated data access mode. Use sqlite for the default local development configuration, sqlserver for the SQL Server provider configuration, or none to generate the application with EF Core data access disabled. |
--skipRestore |
false |
true, false |
Skips the post-create NuGet restore action when set to true. |
Example non-default scaffold:
dotnet new netcoreapp-template `
--name ContosoNoAuthSqlServer `
--authProvider none `
--dbProvider sqlserver
All supported variants preserve the template's core infrastructure guardrails, including structured logging, centralized error handling, health checks, security headers, rate limiting, and safe defaults.
Authentication-disabled variant
The --authProvider none option generates the application with ProjectTemplate:Authentication:Enabled and ProjectTemplate:Authentication:Cookie:Enabled set to false.
The application still includes the authentication and authorization infrastructure so consumers can enable or replace authentication later. Test cases that intentionally exercise protected endpoints may enable test authentication through in-memory test configuration.
SQL Server variant
The --dbProvider sqlserver option excludes the SQLite-specific Data/Migrations history and migration tests from generated output. Consumers must create provider-compatible SQL Server migrations before running dotnet ef database update.
To keep this omission operationally visible, a generated SQL Server scaffold emits a startup warning when no EF Core migrations are present. The warning explains that the SQLite history was intentionally omitted and provides the exact dotnet ef migrations add InitialSqlServer ... command. In the NCAT 2.x line this is advisory: startup continues, and migrations are never generated or applied automatically.
Data-access-disabled variant
The --dbProvider none option generates the application with ProjectTemplate:DataAccess:Provider set to None.
When data access is disabled, EF Core application data access services are not registered, including ApplicationDbContext, IDbContextFactory<ApplicationDbContext>, and EF-backed services that require ApplicationDbContext.
This mode is appropriate for lightweight applications, workers, external modules, or services that use a separate persistence strategy.
Restore, Build, and Test the Generated Project
cd ContosoSecurityPortal
dotnet restore --locked-mode
dotnet build --configuration Release
dotnet test --configuration Release
The generated global.json explicitly selects Microsoft.Testing.Platform, and the generated test project references xunit.v3. This keeps the test runner posture deterministic across local development and CI rather than relying on SDK inference.
Every generated project includes a checked-in packages.lock.json. Use --locked-mode in CI and other repeatable builds so restore fails when declared dependencies and the recorded graph differ. After an intentional dependency change, run dotnet restore --force-evaluate, review the resulting lock-file changes, and commit them with the package update.
Update the Installed Template
Install the newer package version:
dotnet new install NetCoreApplicationTemplate
The .NET SDK updates the installed template package when the package identity matches and the new package version is higher.
Uninstall the Template
dotnet new uninstall NetCoreApplicationTemplate
Local Repository Install
For local authoring and quick iteration, the template can still be installed from the repository root.
On Windows:
dotnet new install .\
On Linux or macOS:
dotnet new install ./
Then generate from a separate working directory:
dotnet new netcoreapp-template -n ContosoSecurityPortal
Local repository install is useful during template development, but package-based install should remain the primary validation path before release.
CI Smoke Test
The CI workflow packs the template package, installs the generated .nupkg, scaffolds a new project with dotnet new netcoreapp-template, validates the scaffolded output and its required lock files against the golden manifest, restores in locked mode, builds the generated output, runs generated tests, and uninstalls the template package.
The smoke test runs on Linux, Windows, and macOS so path handling and package install behavior are validated across supported runner environments.
On Linux runners, CI also validates the Docker consumer path from the generated scaffolded output. The Docker restore layer copies each required project lock file before running dotnet restore --locked-mode. This Docker smoke test builds the generated Docker image, validates docker compose config, starts the generated Compose application, verifies /health/live, captures Compose logs for diagnostics, and tears down the Compose stack during cleanup.
Docker runtime validation is intentionally limited to Linux runners. The goal is to prove that Docker files emitted by the template are usable by a generated consumer project, not to certify Docker host behavior across every operating system.
Distribution Direction
The stable distribution model is a published NuGet template package installable with dotnet new install.
Stable usage follows this pattern:
dotnet new install NetCoreApplicationTemplate
dotnet new netcoreapp-template -n ContosoSecurityPortal