Skip to content

Add ability to specify Windows App SDK version in C# dotnet and VSIX templates#6523

Draft
lauren-ciha wants to merge 13 commits into
mainfrom
user/laurenciha/default-highest-nuget-version-csharp-templates
Draft

Add ability to specify Windows App SDK version in C# dotnet and VSIX templates#6523
lauren-ciha wants to merge 13 commits into
mainfrom
user/laurenciha/default-highest-nuget-version-csharp-templates

Conversation

@lauren-ciha
Copy link
Copy Markdown
Member

@lauren-ciha lauren-ciha commented May 29, 2026

Extends #6407 and resolves #6343

In previous PRs, the UseLatestWindowsAppSDK was used in the dotnet templates to update the template project dependencies to the latest version. However, if this option was unchecked or set to false, no dependencies would be installed at all. This PR fixes this error by setting the default dependency version to the latest version in the ProjectTemplate.csproj themselves with PackageReference and providing parameters to pass in specific NuGet package versions for each template's dependencies.

Before this PR, the VSIX templates installed their packages via the NuGetPackageInstaller wizard, even though C# projects have long had PackageReference support. The reason was to have one implementation to manage package installation for both C# and C++ templates. Now that the Windows App SDK templates extend beyond Visual Studio, it does not make sense for the C# templates to use the Wizard class when evergreen dependency versions can be written into the project files. Further work is needed to completely remove the wizard from the C# VSIX templates, however that is out of scope for this PR. Setting PackageReference... Version="*" simplifies the default NuGet dependency versioning for both dotnet and VSIX templates.

That only covers the default case. To accommodate custom versioning on template generation, I added {dependency}Version parameter for each of the template dependencies. When the parameter is empty, it is replaced with the latest version (*). Other templates have new parameters for their additional dependencies.

Walkthrough with the single-project/blank app template

To illustrate the changes, let's walk through the blank app/single-project packaged app template:

  • dev/Templates/Source/ProjectTemplates/Desktop/CSharp/SingleProjectPackagedApp/ProjectTemplate.csproj no longer has the dotnet conditional because we want VSIX dependencies to be resolved with PackageReference as well.
    *dev/Templates/Source/ProjectTemplates/Desktop/CSharp/SingleProjectPackagedApp/WinUI.Desktop.Cs.SingleProjectPackagedApp.vstemplate sets those CustomParameter to *. This makes sense for the VSIX templates since we do not have the UI to select versions (outside of the scope of this PR)
  • Then in dev/Templates/Dotnet/templates/blank-app/.template.config/template.json, UseLatestWindowsAppSDK has been removed and the default values for the other depdency versions have been replaced to the floating latest stable value (*). This will make the templates easier to maintain in the long run if we want the default value to be the highest stable available. Since the post-actions were updating to the latest version, they're no longer needed. If NuGet restore fails, there is a clear error to the user and since the dependencies have moved into the project file, we don't need to add another version on failure.
  • dev/Templates/Dotnet/templates/blank-app/.template.config/ide.host.json and dev/Templates/Dotnet/templates/blank-app/.template.config/dotnetcli.host.json surface these parameters to the user in Visual Studio and donet CLI respectively

These changes have been made to each of the C# templates.

Finally, dev/Templates/Dotnet/Test-DotnetNewTemplates.ps1 was updated to include tests for the version parameter parsing:

  • If a version parameter is left blank in the dotnet CLI, it's set to *
  • If a real Windows App SDK version is passed in, the instantiated project has that version
  • If multiple versions are pinned, those versions are set in the instantiated templates
  • If a prerelease string is included in the version (e.g. preview), the version is set correctly
  • If an invalid NuGet version was passed in, the parameter is passed to NuGet, but NuGet restore fails
  • If a valid NuGet version was passed in, but was not a WASDK version, the parameter is passed to NuGet, but NuGet restore fails

Considered paths (and the current limitations):

  • Command line/template level parameter validation would reduce the time it would take for someone to realize they made a typo. Unfortunately, parameter-level validation was not supported
  • Hiding the several version input boxes in VS' New Project menu behind a checkbox so that users would not have to look at all their versioning options if they just wanted the default. Unfortunately, although the boolean isVisible can be set, the values are set at instantiation time (e.g. VS' "Create" button) and are not responsive to user input. This is a Visual Studio limitation.

How I validated this PR:

  • Ran Test-DotnetNewTemplates.ps1 - passed
  • Manually installed, opened, and built all of the dotnet tests in VS - passed
  • Built and installed the vsix using build-install-localdev-vsix.ps1 and instantiated and built the templates in VS - passed
  • Running the branch through the aggregator pipeline (user/laurenciha/default-highest-nuget-version-csharp-templates)

A microsoft employee must use /azp run to validate using the pipelines below.

WARNING:
Comments made by azure-pipelines bot maybe inaccurate.
Please see pipeline link to verify that the build is being ran.

For status checks on the main branch, please use TransportPackage-Foundation-PR
(https://microsoft.visualstudio.com/ProjectReunion/_build?definitionId=81063&_a=summary)
and run the build against your PR branch with the default parameters.

lauren-ciha and others added 12 commits June 1, 2026 10:27
…x CS0017 when building the template project in VS
Replace hardcoded Version="*" PackageReferences with *$
template tokens in all 6 shared .csproj files. These tokens are
resolved by the dotnet new template engine (via template.json symbols)
and by the VSIX template engine (via CustomParameter entries).

Add defensive CustomParameter entries with Value="*" to each
.vstemplate file so that VSIX templates resolve the new tokens to
latest-version semantics, matching the dotnet new default behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the UseLatestWindowsAppSDK boolean and hardcoded version
defaults with freeform text parameters (defaultValue="*") that let
users pin specific NuGet package versions at scaffold time via
--wasdk-version, --build-tools-version, etc.

Remove all B17581D1 'update to latest' post-actions since floating
Version="*" already resolves to the latest stable release via NuGet.
The 210D431B restore post-action is retained.

Add version parameters to the class-library template which previously
had none.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the UseLatestWindowsAppSDK IDE entry with version parameter
entries so that IDEs like Visual Studio and Rider surface the new
version pinning options in their template dialogs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Register long and short CLI aliases for each version parameter:
  --wasdk-version / -wasdkv
  --build-tools-version / -btv
  --winapp-version / -wav
  --mvvm-toolkit-version / -mtv  (mvvm-app only)
  --mstest-version / -mv         (unit-test only)
  --test-sdk-version / -tsv      (unit-test only)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add winui-tabview and winui-mvvm to the template test matrix.

Add Assert-CsprojPackageVersion helper function and 6 test scenarios:
  1. Default (no version) produces Version="*"
  2. Single pinned version (--wasdk-version)
  3. All versions pinned
  4. Pre-release version string (e.g. 1.8.0-preview1)
  5. Invalid version: scaffold succeeds, build fails
  6. Nonexistent version (99.99.99): scaffold succeeds, build fails

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Dot-navigation on multiple ItemGroup elements fails when some lack
PackageReference children. Use SelectNodes XPath query instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add useLatestDependencies bool parameter (default: true) to all 6
template.json configs. In ide.host.json, version fields use
isVisible='!useLatestDependencies' so they only appear when the
checkbox is unchecked. CLI behavior is unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@lauren-ciha lauren-ciha force-pushed the user/laurenciha/default-highest-nuget-version-csharp-templates branch from dbefdc4 to 4aa8c5f Compare June 1, 2026 17:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WinUI templates: unchecking UseLatestWindowsAppSDK omits Windows App SDK package references and breaks build

1 participant