Create Your Customizable .NET Project Template Efficiently
Written on
Chapter 1: Introduction to Configurable .NET Project Templates
Creating a configurable .NET project template is an effective way to streamline your development process and focus on the essential aspects of your projects. Modern cloud software development offers tools that facilitate quick deployment at scale, but the repetitive nature of boilerplate code often hampers our progress. By utilizing a well-structured project template, we can eliminate tedious setup tasks and maintain consistency, which is crucial for enhancing speed and efficiency within software teams.
Investing time into crafting your template project is worthwhile, as it amplifies the effectiveness of security measures, testing protocols, and performance strategies across all new projects initiated from it. This guide will employ my recommended .NET project setup, which incorporates Clean Architecture and Domain-Driven Design. You can find the complete code for this template project linked at the end of the article.
Chapter 2: Choosing a Template Engine
There are numerous options available for creating project templates, including GitHub templates, Spotify Backstage, and custom solutions. However, the most powerful option I discovered is the dotnet template engine, known as dotnet new. If you are already working within the .NET ecosystem, this tool allows you to debug and test your template project across various configurations directly within Visual Studio or Rider.
The dotnet new command is integrated into the .NET CLI and is utilized for the default project templates. Templates can be installed from local directories or NuGet packages, making distribution straightforward. Both the dotnet CLI and your IDE can be employed to generate new projects from a template.
Numerous configuration and transformation options are available, enabling your templates to be as sophisticated as necessary. For instance, the .NET Boxed API Template showcases some powerful features.
Chapter 3: Designing Your Template Project
When constructing your template, it's best to avoid incorporating too many domain-specific concepts, as most will not apply to every new project you launch. The sample application we'll utilize builds upon the standard Weather Forecast example provided in the default .NET project templates, including the following components:
- API: ASP.NET 7 REST API with Swagger support
- Angular SPA: Angular Single Page Application hosted using ASP.NET 7
- Database: Integration with Entity Framework Core
- Migrations: Code-First database migrations managed via a console application
Chapter 4: Template Requirements
Utilizing the dotnet template engine, our project template will fulfill the following requirements:
- Rename the Solution, Projects, and Namespaces according to a specified Project Name
- Conditionally add the Web project based on user input
- Conditionally add Test projects based on user input
- Options for Database Type: SQL Server or PostgreSQL
Chapter 5: Implementing the Template
To convert our project into a template, we simply need to create a special folder called .template.config in the root of our solution. The template.json file, which contains essential configuration and metadata for the template, is the key addition.
Once configured, our project can be installed as a template and used to generate new projects.
Section 5.1: Renaming Solution, Projects, and Namespaces
You likely do not want every new project to carry the name 'CleanArchitecture.' By ensuring the sourceName property matches the prefix for your Solution, Projects, and Namespaces, all will be automatically replaced with the 'Project name' specified upon creating new projects from your template.
Section 5.2: Condition-Based File Management
In your initial setup, include any elements you believe may be useful for your projects. When new projects are created from the template, we can selectively remove code blocks, files, and even entire projects based on the provided configuration.
For our example, we will implement configuration that conditionally adds the following projects:
- Angular Web Project
- All Test Projects
To facilitate this, we will introduce symbols to our template.json. These symbols serve as variables to manage transformations and file exclusions during project generation. Boolean parameters can create checkboxes for users to decide whether to include conditional projects.
Section 5.3: Database Type Configuration
We will support two options for Database selection:
- SQL Server
- PostgreSQL
A choice parameter will present this option as a dropdown during project creation. Generally, it is easier to work with choice parameters by creating an additional boolean computed symbol for use throughout our template.
Section 5.4: Conditionally Adding Code
To accommodate different Entity Framework database providers, we need to ensure our projects include the appropriate code for:
- Selecting the correct EF Database Provider NuGet Package
- Configuring the provider with DbContextOptions
- Setting the correct connection string in the appsettings.json
- Creating the necessary docker-compose service for database setup
The dotnet template engine allows for the inclusion of different code sections in your output projects based on any symbols defined in your template.json.
Section 5.5: Debugging and Testing Your Template
Since our template project is a fully functional .NET solution, we can run and debug it for testing purposes. A useful trick is to run projects using various configurations by adjusting the symbols in relevant .csproj files.
Chapter 6: Installing Your Template
You can install your template using the following command:
dotnet new install .
To uninstall, use:
dotnet new uninstall .
Once installed, your template should appear as an option when creating new projects.
Final Thoughts
The techniques outlined above can be adapted to achieve a wide array of functionalities within your project templates. I hope this guide has sparked some ideas for your own projects! You can find all the code for the template project available on my GitHub.