Thank you for your interest in contributing to .NET Scaffolding! This document provides guidelines and instructions for contributing to this repository.
- Code of Conduct
- Contributor License Agreement
- Ways to Contribute
- Getting Started
- Repository Structure
- Development Workflow
- Making Code Changes
- Coding Conventions
- Testing Your Changes
- Debugging
- Submitting Your Changes
- Reporting Issues
- Additional Resources
- License
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution.
- When you open a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (for example, with a status check or comment).
- You only need to sign the CLA once across all Microsoft/.NET Foundation repositories.
- Simply follow the instructions provided by the bot and complete the signing process before your PR can be merged.
For details, see https://cla.opensource.microsoft.com/.
There are many ways to contribute beyond writing code:
- Report bugs: File clear, reproducible issues.
- Fix bugs: Look for issues labeled
bugorhelp wanted. Before you start, reproduce the bug yourself first to confirm it still occurs on the latestmain— some issues are already fixed or environment-specific. Capture the exact reproduction steps so you can re-run them after your fix to verify it's resolved. - Add or update templates and scaffolders: See Making Code Changes.
- Improve documentation: Fix typos, clarify instructions, or add examples in the
docs/folder and READMEs. - Write tests: Increase coverage for existing functionality.
- Answer questions: Help others in GitHub Discussions and Issues.
If you're new, look for issues tagged good first issue or help wanted — these are curated to be approachable. For anything non-trivial, please open or comment on an issue first so we can align on the approach before you invest significant time.
Before you begin, ensure you have the following installed:
-
Preview .NET SDK:
- Download a preview version that matches the version in
global.jsonat the root of the repository - Reference: https://github.com/dotnet/sdk/blob/main/documentation/package-table.md
- Download a preview version that matches the version in
-
Development Environment:
- Visual Studio 2022 (latest preview) OR
- Visual Studio Code with C# Dev Kit extension
-
Git: For cloning the repository and version control
-
Azure CLI (if working on Azure-related features):
az login
git clone https://github.com/dotnet/Scaffolding.git
cd ScaffoldingWe recommend cloning under your user profile directory for easier access.
Understanding the repository structure is crucial for making contributions:
Scaffolding/
├── src/
│ ├── dotnet-scaffolding/
│ │ └── dotnet-scaffold/
│ │ ├── AspNet/ # ASP.NET scaffolders
│ │ │ ├── Templates/ # Templates organized by .NET version
│ │ │ │ ├── net8.0/
│ │ │ │ ├── net9.0/
│ │ │ │ ├── net10.0/ # .NET 10 templates
│ │ │ │ │ ├── BlazorCrud/
│ │ │ │ │ ├── BlazorEntraId/
│ │ │ │ │ ├── BlazorIdentity/
│ │ │ │ │ ├── Identity/
│ │ │ │ │ ├── MinimalApi/
│ │ │ │ │ ├── RazorPages/
│ │ │ │ │ ├── Views/
│ │ │ │ │ └── CodeModificationConfigs/ # JSON configs for code changes
│ │ │ │ └── net11.0/
│ │ │ ├── ScaffoldSteps/ # Step implementations
│ │ │ ├── Commands/ # Command definitions
│ │ │ └── Helpers/ # Helper utilities
│ │ ├── Aspire/ # Aspire scaffolders
│ │ │ └── CodeModificationConfigs/
│ │ │ └── net11.0/ # Aspire code modification configs
│ │ └── ...
│ ├── MSIdentityScaffolding/ # dotnet msidentity tool
│ └── Scaffolding/ # Legacy scaffolding (maintenance mode)
├── test/
│ ├── dotnet-scaffolding/
│ │ └── dotnet-scaffold.Tests/
│ │ └── AspNet/ # Unit tests for ASP.NET scaffolders
│ └── MSIdentityScaffolding/
├── docs/ # Documentation
│ ├── Getting-Started.md
│ └── ...
├── scripts/ # Build and install scripts
│ ├── install-scaffold.cmd
│ └── install-scaffold.sh
└── All.sln # Main solution file
-
Templates: Located in
src/dotnet-scaffolding/dotnet-scaffold/AspNet/Templates/{version}/- Contains T4 templates (
.ttfiles) for generating code - Organized by .NET version (net8.0, net9.0, net10.0, net11.0)
- Each scaffolder type has its own subfolder
- Contains T4 templates (
-
CodeModificationConfigs: Located in:
src/dotnet-scaffolding/dotnet-scaffold/AspNet/Templates/{version}/CodeModificationConfigs/src/dotnet-scaffolding/dotnet-scaffold/Aspire/CodeModificationConfigs/{version}/- Contains JSON files that define code modifications
- Examples:
blazorEntraChanges.json,identityChanges.json
-
ScaffoldSteps: Located in
src/dotnet-scaffolding/dotnet-scaffold/AspNet/ScaffoldSteps/- Contains the logic for each scaffolding step
- Implement the
ScaffoldStepbase class
-
Tests: Located in
test/dotnet-scaffolding/dotnet-scaffold.Tests/AspNet/- Unit tests for scaffolding functionality
- Mirror the structure of the source code
-
Open the solution in your IDE:
# Visual Studio start All.sln # Visual Studio Code code .
-
Restore dependencies:
dotnet restore
-
Build the solution:
dotnet build
Tip: The repository also ships convenience scripts at the root that restore and build with the pinned SDK from
global.json:build.cmd # Windows ./build.sh # macOS/LinuxTo launch a fully configured IDE that uses the repo-local SDK, use
startvs.cmd(Visual Studio) orstart-code.cmd(VS Code) instead of opening the solution directly. This ensures the correct preview SDK is picked up.
After making changes, install your local build to test:
Windows (cmd):
scripts\install-scaffold.cmdmacOS/Linux or Windows (PowerShell):
scripts/install-scaffold.shThese scripts automate the full local install cycle. Under the hood they:
- Kill any running
dotnet.exeprocesses (so the tool isn't locked). - Clear the previous
artifactsoutput and pack a fresh NuGet package viadotnet pack(Debug configuration). - Uninstall the existing global
Microsoft.dotnet-scaffoldtool. - Purge the cached scaffolding packages from your NuGet cache (
Microsoft.dotnet-scaffold,Microsoft.DotNet.Scaffolding.Internal,Microsoft.DotNet.Scaffolding.Core) so the new build isn't shadowed by a cached copy. - Reinstall the tool globally from your freshly built local package, making
dotnet scaffoldpoint at your changes.
Because the tool is installed globally, you must re-run the install script after every change you want to test — a plain dotnet build updates the binaries in artifacts/ but does not update the globally installed dotnet scaffold command.
This is the core inner loop you'll repeat while working:
-
Make Changes: Edit the code, templates, or configs.
-
Reinstall: Run the install script for your platform to rebuild, repack, and reinstall the global tool:
scripts\install-scaffold.cmd :: Windows (cmd)
scripts/install-scaffold.sh # macOS/Linux(The script builds for you, so a separate
dotnet buildstep isn't required before running it.)Verify the install script completed successfully. Watch the output and confirm it finishes without errors — the final
dotnet tool install -g Microsoft.dotnet-scaffold ...step should report that the tool was installed. If the script fails partway (for example, because adotnetprocess was still locking files, or the pack step errored), your changes won't be deployed. Re-run the script after resolving the error, and sanity-check the active version with:dotnet scaffold --version
-
Test: Run
dotnet scaffold ...against a test project to exercise your change (see Testing Your Changes). -
Repeat: Iterate until the behavior is correct.
Important: If you skip the install step,
dotnet scaffoldwill keep running the previously installed version and you won't see your changes. When in doubt, re-run the install script. If results still look stale, delete.configfolders and clear the NuGet cache (see Common Issues).
Templates are the source files used to generate code in user projects.
- Navigate to
src/dotnet-scaffolding/dotnet-scaffold/AspNet/Templates/ - Choose the .NET version folder you're updating (e.g.,
net10.0/,net11.0/) - Find the scaffolder type subfolder (e.g.,
BlazorEntraId/,Identity/) - Edit the
.tt(T4 template) files
Example: Updating Blazor Entra ID templates for .NET 10:
src/dotnet-scaffolding/dotnet-scaffold/AspNet/Templates/net10.0/BlazorEntraId/
├── AuthenticationStateProvider.tt
├── LoginDisplay.tt
└── ...
- Test your templates: Ensure generated code compiles and runs
- Follow C# conventions: Use proper naming, formatting, and patterns
- Add comments: Include XML documentation for public APIs
- Parameterize properly: Use template parameters for dynamic values
- Keep it simple: Templates should be readable and maintainable
Code modification configs are JSON files that define how to modify existing code files.
For ASP.NET scaffolders:
src/dotnet-scaffolding/dotnet-scaffold/AspNet/Templates/{version}/CodeModificationConfigs/
For Aspire scaffolders:
src/dotnet-scaffolding/dotnet-scaffold/Aspire/CodeModificationConfigs/{version}/
Example Config Files:
blazorEntraChanges.json- Blazor Entra ID code modificationsidentityChanges.json- ASP.NET Identity modificationsminimalApiChanges.json- Minimal API modifications
{
"Files": [
{
"FilePath": "Program.cs",
"Usings": [
"Microsoft.AspNetCore.Authentication",
"Microsoft.Identity.Web"
],
"CodeChanges": [
{
"Block": "GlobalStatements",
"CodeSnippet": "builder.Services.AddAuthentication(...);"
}
]
}
]
}- Validate JSON: Ensure your JSON is well-formed
- Test modifications: Verify code changes apply correctly
- Be specific: Use precise code blocks and insertion points
- Handle edge cases: Consider different project structures
- Create a new subfolder in
AspNet/Templates/{version}/ - Add your T4 templates
- Create a code modification config if needed
- Implement scaffold steps in
AspNet/ScaffoldSteps/ - Register your scaffolder in
AspNetCommandService.cs - Add unit tests in
test/.../AspNet/
- Locate the scaffolder in
AspNet/Templates/{version}/ - Edit the appropriate template files or config files
- Update corresponding scaffold steps if needed
- Update existing tests or add new ones
- Test thoroughly
Consistent code makes review faster and the codebase easier to maintain.
- Follow
.editorconfig: The repository root contains an.editorconfigthat defines indentation, spacing,usingordering, and naming rules. Most IDEs apply it automatically. - Match the surrounding code: Prefer the patterns already used in the file you're editing.
- Format before committing: Run
dotnet formatto apply style fixes and catch violations early:dotnet format All.sln
- General C# guidance: Follow the .NET runtime coding style where this repo does not specify otherwise.
- Use
PascalCasefor types and public members,camelCasefor locals and parameters, and_camelCasefor private fields. - Add XML documentation comments (
///) to public APIs. - Keep methods focused and avoid unrelated changes in the same PR.
- Write clear, imperative-mood subject lines (e.g., "Add Entra ID logout template" rather than "Added" or "Adds").
- Keep the subject under ~72 characters and add a body explaining why when the change isn't obvious.
- Reference related issues in the body (e.g.,
Fixes #123).
Use branch names in the format dev/<alias>/<description> — the literal dev, then your user alias, then a kebab-case description of the bug or feature after the second /:
dev/jdoe/blazor-identity-logout
dev/jdoe/minimal-api-null-ref
dev/jdoe/contributing-updates
Testing is required for all contributions. Contributors must add unit tests for new functionality.
# Create a test Blazor project
dotnet new blazorserver -n TestApp -f net10.0
cd TestApp# Example: Add Entra ID authentication
dotnet scaffold aspnet entra-id --help
# Or run without options for interactive mode
dotnet scaffold aspnet entra-id- Check that files were created correctly
- Ensure the project builds:
dotnet build
- Run the project and test functionality:
dotnet run
cd ..
rm -rf TestAppAll code changes must include unit tests.
Tests are organized to mirror the source structure:
test/dotnet-scaffolding/dotnet-scaffold.Tests/AspNet/
├── Helpers/
├── ScaffoldSteps/
└── ...
- Create or locate the appropriate test file
- Use xUnit framework (already configured)
- Follow existing test patterns
- Test both success and failure scenarios
Example Test Structure:
using Xunit;
namespace Microsoft.DotNet.Tools.Scaffold.Tests.AspNet
{
public class MyScaffolderTests
{
[Fact]
public void Should_GenerateCorrectCode_When_ValidInput()
{
// Arrange
var input = "test";
// Act
var result = MyScaffolder.Generate(input);
// Assert
Assert.NotNull(result);
Assert.Contains("expected", result);
}
[Fact]
public void Should_ThrowException_When_InvalidInput()
{
// Arrange
var input = "";
// Act & Assert
Assert.Throws<ArgumentException>(() =>
MyScaffolder.Generate(input));
}
}
}You must run the test suite and confirm it passes before opening a pull request. A PR with failing or unrun tests will not be merged, and CI will run these same tests on your branch.
# Run the entire test suite (do this before every PR)
dotnet test All.sln
# Run a single test project (faster inner loop)
dotnet test test/dotnet-scaffolding/dotnet-scaffold.Tests/dotnet-scaffold.Tests.csproj
# Run only the tests related to your change using a filter
dotnet test test/dotnet-scaffolding/dotnet-scaffold.Tests/dotnet-scaffold.Tests.csproj --filter "FullyQualifiedName~BlazorEntra"
# Run with detailed output to diagnose a failure
dotnet test test/dotnet-scaffolding/dotnet-scaffold.Tests/dotnet-scaffold.Tests.csproj -v detailedExample — full pre-PR test run:
# From the repository root
dotnet test All.sln -c DebugConfirm the summary reports Failed: 0 for every test project before you push and open your PR. If any test fails, fix it (or update the test if the behavior intentionally changed) before submitting.
Note: Some end-to-end integration tests are known to be flaky or are intentionally skipped (for example,
net11/preview-SDK scaffolding tests and tests needing real Azure AD credentials). Before assuming a failure is caused by your change, check docs/KNOWN_FLAKY_TESTS.md and re-run the test in isolation.
- Write tests first (TDD approach recommended)
- Test edge cases: Empty inputs, nulls, invalid data
- Use descriptive names:
Should_DoSomething_When_Condition - Keep tests focused: One assertion per test when possible
- Mock dependencies: Use mocking for external dependencies
- Test both paths: Success and failure scenarios
For larger changes, perform integration testing:
- Create multiple test projects (Blazor Server, Blazor WASM, MVC, etc.)
- Run scaffolders on each project type
- Build and run each project
- Verify functionality end-to-end
- Open
All.slnin Visual Studio - Set breakpoints in your code
- Add the following line near the top of the entry point you want to debug:
System.Diagnostics.Debugger.Launch();
- Run the install script to deploy your changes
- Execute
dotnet scaffoldfrom a terminal - The debugger will launch automatically - attach to the process
- Open the repository in VS Code
- Install the C# Dev Kit extension
- Create a launch configuration (
.vscode/launch.json) - Set breakpoints
- Use F5 to start debugging
.configfolders: Delete.configfolders in both the scaffolding repo and test projects- Overlapping SDK versions: Ensure only one version of a preview SDK is installed
- Package cache: Clear NuGet cache if experiencing package issues:
dotnet nuget locals all --clear
- ✅ Build succeeds:
dotnet buildcompletes without errors - ✅ All tests pass:
dotnet testshows all green - ✅ New tests added: Unit tests cover your changes
- ✅ Manual testing done: Verified with actual scaffolding scenarios
- ✅ Code formatted:
dotnet formatrun and conventions followed - ✅ Documentation updated: Update relevant docs if needed
- ✅ CLA signed: Contributor License Agreement completed
-
Fork the repository (if you haven't already)
-
Create a feature branch:
git checkout -b feature/my-awesome-feature
-
Make your changes and commit:
git add . git commit -m "Add awesome feature for Blazor scaffolding"
-
Push to your fork:
git push origin feature/my-awesome-feature
-
Open a Pull Request on GitHub:
- Provide a clear title and description
- Reference any related issues
- Describe what you changed and why
- Include testing steps
- Clear description: Explain what changes you made and why
- Link issues: Reference related GitHub issues
- Small PRs: Keep changes focused and manageable
- Test coverage: Include test results or screenshots
- Documentation: Update docs if you changed behavior
- Follow feedback: Be responsive to code review comments
- A maintainer will review your PR
- Address any feedback or requested changes
- Once approved, your changes will be merged
- Your contribution will be included in the next release!
Do not report security issues publicly.
Report security issues and bugs privately to:
- Email: secure@microsoft.com
- Response time: Within 24 hours
- More info: Security TechCenter
When reporting bugs, please include:
- Description: Clear description of the bug
- Steps to reproduce:
1. Run dotnet new blazorserver 2. Run dotnet scaffold aspnet entra-id 3. See error... - Expected behavior: What you expected to happen
- Actual behavior: What actually happened
- Environment:
- OS: Windows 11, macOS 14, etc.
- .NET SDK version:
dotnet --version - Scaffolding version
- Logs/Error messages: Full error output
- Project type: Blazor Server, MVC, Web API, etc.
For feature requests:
- Check if it already exists in issues
- Provide a clear use case
- Describe the expected behavior
- Consider implementation approach
- Be open to discussion and alternatives
- Getting Started: docs/Getting-Started.md
- Known Flaky/Skipped Tests: docs/KNOWN_FLAKY_TESTS.md
- Entra ID Scaffolder: docs/ENTRA_ID_SCAFFOLDER_DOCUMENTATION.md
- Main README: README.md
- GitHub Issues: For bugs and feature requests
- GitHub Discussions: For questions and community support
- Stack Overflow: Tag your questions with
dotnet-scaffolding
# Build the solution
dotnet build
# Run tests (run before every PR)
dotnet test All.sln
# Install local changes
scripts/install-scaffold.cmd # Windows
scripts/install-scaffold.sh # macOS/Linux
# Test your changes
cd ~/TestProject
dotnet scaffold aspnet --help| Component | Location |
|---|---|
| ASP.NET Templates | src/dotnet-scaffolding/dotnet-scaffold/AspNet/Templates/{version}/ |
| Code Modification Configs (ASP.NET) | src/dotnet-scaffolding/dotnet-scaffold/AspNet/Templates/{version}/CodeModificationConfigs/ |
| Code Modification Configs (Aspire) | src/dotnet-scaffolding/dotnet-scaffold/Aspire/CodeModificationConfigs/{version}/ |
| Scaffold Steps | src/dotnet-scaffolding/dotnet-scaffold/AspNet/ScaffoldSteps/ |
| Unit Tests | test/dotnet-scaffolding/dotnet-scaffold.Tests/AspNet/ |
| Documentation | docs/ |
By contributing to this repository, you agree that your contributions will be licensed under the same license that covers the project. See the LICENSE file for the full terms. Do not contribute code, templates, or assets that you do not have the right to license under these terms.
Thank you for contributing to .NET Scaffolding! Your contributions help make .NET development better for everyone.
If you have questions or need help, don't hesitate to:
- Open a GitHub issue
- Start a discussion
- Reach out to the maintainers
Happy coding! 🚀