upgrading-dotnet

Upgrade .NET projects to newer versions. Use when upgrading TargetFramework in csproj/vbproj/fsproj files, migrating between .NET versions, configuring global.json, pinning SDK versions, updating CI/CD pipelines for .NET, or troubleshooting .NET upgrade issues.

$ 安裝

git clone https://github.com/johnlokerse/azure-devops-bicep-local-deploy /tmp/azure-devops-bicep-local-deploy && cp -r /tmp/azure-devops-bicep-local-deploy/.github/skills/upgrading-dotnet ~/.claude/skills/azure-devops-bicep-local-deploy

// tip: Run this command in your terminal to install the skill


name: upgrading-dotnet description: Upgrade .NET projects to newer versions. Use when upgrading TargetFramework in csproj/vbproj/fsproj files, migrating between .NET versions, configuring global.json, pinning SDK versions, updating CI/CD pipelines for .NET, or troubleshooting .NET upgrade issues.

.NET Project Upgrade Skill

When to Use This Skill

  • Upgrading project target frameworks (e.g., net6.0net9.0)
  • Updating .NET SDK versions across projects
  • Migrating multiple projects in a solution
  • Version pinning and controlled rollouts
  • Updating CI/CD pipelines for new .NET versions
  • Preparing hosting environments for new runtimes

Quick Start: Basic Upgrade Process

1. Identify Projects to Upgrade

List all project files that need upgrading:

find . -name "*.csproj" -o -name "*.vbproj" -o -name "*.fsproj"

2. Update Project Files (Minimum Required Change)

Open each project file (.csproj, .vbproj, or .fsproj) and update the <TargetFramework> property:

Before:

<PropertyGroup>
  <TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

After (upgrading to .NET 9):

<PropertyGroup>
  <TargetFramework>net9.0</TargetFramework>
</PropertyGroup>

For multi-targeted projects, update <TargetFrameworks>:

<PropertyGroup>
  <TargetFrameworks>net8.0;net9.0</TargetFrameworks>
</PropertyGroup>

3. Restore Workloads

If using specialized workloads (MAUI, ASP.NET, etc.):

dotnet workload restore

4. Build and Test

dotnet build
dotnet test

The SDK will provide warnings and errors to guide further changes.

Advanced: Version Pinning Strategies

Pin SDK Version with global.json

Create or update global.json in your solution root to control which SDK version is used:

dotnet new globaljson --sdk-version 9.0.100 --roll-forward latestFeature

This ensures consistent builds across different machines and CI environments.

File structure after:

solution-root/
├── global.json          (pins SDK version)
├── src/
│   ├── Project1/
│   └── Project2/
└── tests/

Control Analyzer Behavior

Lock analyzer rules to a specific .NET version to prevent new warnings on upgrade:

<PropertyGroup>
  <AnalysisLevel>9.0</AnalysisLevel>
</PropertyGroup>

This is useful when upgrading gradually—prevents new analyzer rules from breaking builds before you're ready to address them.

Manage Package Versions

Option A: Central Package Management (Recommended)

Create Directory.Packages.props in solution root:

<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>

  <ItemGroup>
    <PackageVersion Include="Microsoft.Extensions.AI" Version="9.10.1" />
    <PackageVersion Include="Azure.Identity" Version="1.17.0" />
  </ItemGroup>
</Project>

In project files, reference without version:

<ItemGroup>
  <PackageReference Include="Microsoft.Extensions.AI" />
  <PackageReference Include="Azure.Identity" />
</ItemGroup>

Option B: Package Lock Files

Enable lock files to ensure reproducible restores:

<PropertyGroup>
  <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
  <RestoreLockedMode>true</RestoreLockedMode>
</PropertyGroup>

Generate lock file:

dotnet restore

CI/CD Pipeline Updates

Update your CI/CD pipeline to use the new SDK version. For GitHub Actions:

Before:

- name: Setup .NET
  uses: actions/setup-dotnet@v4
  with:
    dotnet-version: '8.0'

After:

- name: Setup .NET
  uses: actions/setup-dotnet@v4
  with:
    dotnet-version: '9.0'

Multi-Project Upgrade Checklist

Copy this checklist and track progress:

Upgrade Progress:
- [ ] Review breaking changes for target .NET version
- [ ] Update all .csproj files to new target framework
- [ ] Run dotnet workload restore if needed
- [ ] Build entire solution: dotnet build
- [ ] Run full test suite: dotnet test
- [ ] Update global.json if using version pinning
- [ ] Update CI/CD pipeline configuration
- [ ] Test in CI/CD environment
- [ ] Commit changes

Breaking Changes and Migration

Check for breaking changes specific to your target version:

Hosting Environment Updates

Docker

Update Dockerfile FROM statements:

# Old
FROM mcr.microsoft.com/dotnet/aspnet:8.0

# New
FROM mcr.microsoft.com/dotnet/aspnet:9.0

Azure App Service

Configuration changes are required through Azure Portal or IaC (e.g., Bicep, Terraform).

Linux Servers

Install new .NET runtime via package manager:

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y dotnet-runtime-9.0

Troubleshooting

Validation Loop

  1. Run dotnet build
  2. If errors: review messages, fix issues, repeat step 1
  3. Run dotnet test
  4. If failures: fix tests, repeat step 3
  5. Only proceed when both pass

Build Fails After Update

  1. Check error messages—SDK provides guidance
  2. Review breaking changes for your target version
  3. Update NuGet packages that may have new version requirements
  4. Run dotnet clean and rebuild

Tests Fail

  • Run tests individually to isolate issues
  • Check for API changes in updated packages
  • Review test framework compatibility (e.g., xUnit, NUnit versions)

CI/CD Pipeline Fails

  • Verify new SDK version is available in CI environment
  • Check global.json is in repo root (CI should respect it)
  • Update any hardcoded version references in pipeline

Key Resources

Examples by Scenario

Scenario 1: Simple Single-Project Upgrade

For a single .csproj project:

  1. Update <TargetFramework>net9.0</TargetFramework>
  2. Run dotnet build
  3. Run dotnet test
  4. Commit with message: "Upgrade to .NET 9"

Scenario 2: Multi-Project Solution with CI/CD

For solutions with multiple projects and GitHub Actions:

  1. Update all .csproj files in the solution
  2. Create/update global.json in solution root
  3. Update .github/workflows/*.yml to use new version
  4. Run full test suite locally: dotnet test
  5. Push and verify CI passes
  6. Commit message: "Upgrade solution to .NET 9 (includes CI/CD updates)"

Scenario 3: Gradual Multi-Version Support

For libraries supporting multiple .NET versions:

  1. Update <TargetFrameworks>net8.0;net9.0</TargetFrameworks>
  2. Test on both versions: dotnet test --framework net8.0 && dotnet test --framework net9.0
  3. Document supported versions in README
  4. Gradually drop old version support in future releases