|
| 1 | +--- |
| 2 | +name: upgrading-dotnet |
| 3 | +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. |
| 4 | +--- |
| 5 | + |
| 6 | +# .NET Project Upgrade Skill |
| 7 | + |
| 8 | +## When to Use This Skill |
| 9 | + |
| 10 | +- Upgrading project target frameworks (e.g., `net6.0` → `net9.0`) |
| 11 | +- Updating .NET SDK versions across projects |
| 12 | +- Migrating multiple projects in a solution |
| 13 | +- Version pinning and controlled rollouts |
| 14 | +- Updating CI/CD pipelines for new .NET versions |
| 15 | +- Preparing hosting environments for new runtimes |
| 16 | + |
| 17 | +## Quick Start: Basic Upgrade Process |
| 18 | + |
| 19 | +### 1. Identify Projects to Upgrade |
| 20 | + |
| 21 | +List all project files that need upgrading: |
| 22 | + |
| 23 | +```bash |
| 24 | +find . -name "*.csproj" -o -name "*.vbproj" -o -name "*.fsproj" |
| 25 | +``` |
| 26 | + |
| 27 | +### 2. Update Project Files (Minimum Required Change) |
| 28 | + |
| 29 | +Open each project file (`.csproj`, `.vbproj`, or `.fsproj`) and update the `<TargetFramework>` property: |
| 30 | + |
| 31 | +**Before:** |
| 32 | + |
| 33 | +```xml |
| 34 | +<PropertyGroup> |
| 35 | + <TargetFramework>net8.0</TargetFramework> |
| 36 | +</PropertyGroup> |
| 37 | +``` |
| 38 | + |
| 39 | +**After (upgrading to .NET 9):** |
| 40 | + |
| 41 | +```xml |
| 42 | +<PropertyGroup> |
| 43 | + <TargetFramework>net9.0</TargetFramework> |
| 44 | +</PropertyGroup> |
| 45 | +``` |
| 46 | + |
| 47 | +For multi-targeted projects, update `<TargetFrameworks>`: |
| 48 | + |
| 49 | +```xml |
| 50 | +<PropertyGroup> |
| 51 | + <TargetFrameworks>net8.0;net9.0</TargetFrameworks> |
| 52 | +</PropertyGroup> |
| 53 | +``` |
| 54 | + |
| 55 | +### 3. Restore Workloads |
| 56 | + |
| 57 | +If using specialized workloads (MAUI, ASP.NET, etc.): |
| 58 | + |
| 59 | +```bash |
| 60 | +dotnet workload restore |
| 61 | +``` |
| 62 | + |
| 63 | +### 4. Build and Test |
| 64 | + |
| 65 | +```bash |
| 66 | +dotnet build |
| 67 | +dotnet test |
| 68 | +``` |
| 69 | + |
| 70 | +The SDK will provide warnings and errors to guide further changes. |
| 71 | + |
| 72 | +## Advanced: Version Pinning Strategies |
| 73 | + |
| 74 | +### Pin SDK Version with global.json |
| 75 | + |
| 76 | +Create or update `global.json` in your solution root to control which SDK version is used: |
| 77 | + |
| 78 | +```bash |
| 79 | +dotnet new globaljson --sdk-version 9.0.100 --roll-forward latestFeature |
| 80 | +``` |
| 81 | + |
| 82 | +This ensures consistent builds across different machines and CI environments. |
| 83 | + |
| 84 | +**File structure after:** |
| 85 | + |
| 86 | +```text |
| 87 | +solution-root/ |
| 88 | +├── global.json (pins SDK version) |
| 89 | +├── src/ |
| 90 | +│ ├── Project1/ |
| 91 | +│ └── Project2/ |
| 92 | +└── tests/ |
| 93 | +``` |
| 94 | + |
| 95 | +### Control Analyzer Behavior |
| 96 | + |
| 97 | +Lock analyzer rules to a specific .NET version to prevent new warnings on upgrade: |
| 98 | + |
| 99 | +```xml |
| 100 | +<PropertyGroup> |
| 101 | + <AnalysisLevel>9.0</AnalysisLevel> |
| 102 | +</PropertyGroup> |
| 103 | +``` |
| 104 | + |
| 105 | +This is useful when upgrading gradually—prevents new analyzer rules from breaking builds before you're ready to address them. |
| 106 | + |
| 107 | +### Manage Package Versions |
| 108 | + |
| 109 | +#### Option A: Central Package Management (Recommended) |
| 110 | + |
| 111 | +Create `Directory.Packages.props` in solution root: |
| 112 | + |
| 113 | +```xml |
| 114 | +<Project> |
| 115 | + <PropertyGroup> |
| 116 | + <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> |
| 117 | + </PropertyGroup> |
| 118 | + |
| 119 | + <ItemGroup> |
| 120 | + <PackageVersion Include="Microsoft.Extensions.AI" Version="9.10.1" /> |
| 121 | + <PackageVersion Include="Azure.Identity" Version="1.17.0" /> |
| 122 | + </ItemGroup> |
| 123 | +</Project> |
| 124 | +``` |
| 125 | + |
| 126 | +In project files, reference without version: |
| 127 | + |
| 128 | +```xml |
| 129 | +<ItemGroup> |
| 130 | + <PackageReference Include="Microsoft.Extensions.AI" /> |
| 131 | + <PackageReference Include="Azure.Identity" /> |
| 132 | +</ItemGroup> |
| 133 | +``` |
| 134 | + |
| 135 | +#### Option B: Package Lock Files |
| 136 | + |
| 137 | +Enable lock files to ensure reproducible restores: |
| 138 | + |
| 139 | +```xml |
| 140 | +<PropertyGroup> |
| 141 | + <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile> |
| 142 | + <RestoreLockedMode>true</RestoreLockedMode> |
| 143 | +</PropertyGroup> |
| 144 | +``` |
| 145 | + |
| 146 | +Generate lock file: |
| 147 | + |
| 148 | +```bash |
| 149 | +dotnet restore |
| 150 | +``` |
| 151 | + |
| 152 | +## CI/CD Pipeline Updates |
| 153 | + |
| 154 | +Update your CI/CD pipeline to use the new SDK version. For GitHub Actions: |
| 155 | + |
| 156 | +**Before:** |
| 157 | + |
| 158 | +```yaml |
| 159 | +- name: Setup .NET |
| 160 | + uses: actions/setup-dotnet@v4 |
| 161 | + with: |
| 162 | + dotnet-version: '8.0' |
| 163 | +``` |
| 164 | +
|
| 165 | +**After:** |
| 166 | +
|
| 167 | +```yaml |
| 168 | +- name: Setup .NET |
| 169 | + uses: actions/setup-dotnet@v4 |
| 170 | + with: |
| 171 | + dotnet-version: '9.0' |
| 172 | +``` |
| 173 | +
|
| 174 | +## Multi-Project Upgrade Checklist |
| 175 | +
|
| 176 | +Copy this checklist and track progress: |
| 177 | +
|
| 178 | +```text |
| 179 | +Upgrade Progress: |
| 180 | +- [ ] Review breaking changes for target .NET version |
| 181 | +- [ ] Update all .csproj files to new target framework |
| 182 | +- [ ] Run dotnet workload restore if needed |
| 183 | +- [ ] Build entire solution: dotnet build |
| 184 | +- [ ] Run full test suite: dotnet test |
| 185 | +- [ ] Update global.json if using version pinning |
| 186 | +- [ ] Update CI/CD pipeline configuration |
| 187 | +- [ ] Test in CI/CD environment |
| 188 | +- [ ] Commit changes |
| 189 | +``` |
| 190 | +
|
| 191 | +## Breaking Changes and Migration |
| 192 | +
|
| 193 | +Check for breaking changes specific to your target version: |
| 194 | +
|
| 195 | +- [**.NET 9**](https://learn.microsoft.com/en-us/dotnet/core/compatibility/9.0) |
| 196 | +- [**.NET 10**](https://learn.microsoft.com/en-us/dotnet/core/compatibility/10.0) |
| 197 | +- [**ASP.NET Core**](https://learn.microsoft.com/en-us/aspnet/core/migration/) |
| 198 | +
|
| 199 | +## Hosting Environment Updates |
| 200 | +
|
| 201 | +### Docker |
| 202 | +
|
| 203 | +Update Dockerfile `FROM` statements: |
| 204 | + |
| 205 | +```dockerfile |
| 206 | +# Old |
| 207 | +FROM mcr.microsoft.com/dotnet/aspnet:8.0 |
| 208 | +
|
| 209 | +# New |
| 210 | +FROM mcr.microsoft.com/dotnet/aspnet:9.0 |
| 211 | +``` |
| 212 | + |
| 213 | +### Azure App Service |
| 214 | + |
| 215 | +Configuration changes are required through Azure Portal or IaC (e.g., Bicep, Terraform). |
| 216 | + |
| 217 | +### Linux Servers |
| 218 | + |
| 219 | +Install new .NET runtime via package manager: |
| 220 | + |
| 221 | +```bash |
| 222 | +# Ubuntu/Debian |
| 223 | +sudo apt-get update |
| 224 | +sudo apt-get install -y dotnet-runtime-9.0 |
| 225 | +``` |
| 226 | + |
| 227 | +## Troubleshooting |
| 228 | + |
| 229 | +### Validation Loop |
| 230 | + |
| 231 | +1. Run `dotnet build` |
| 232 | +2. If errors: review messages, fix issues, repeat step 1 |
| 233 | +3. Run `dotnet test` |
| 234 | +4. If failures: fix tests, repeat step 3 |
| 235 | +5. **Only proceed when both pass** |
| 236 | + |
| 237 | +### Build Fails After Update |
| 238 | + |
| 239 | +1. Check error messages—SDK provides guidance |
| 240 | +2. Review breaking changes for your target version |
| 241 | +3. Update NuGet packages that may have new version requirements |
| 242 | +4. Run `dotnet clean` and rebuild |
| 243 | + |
| 244 | +### Tests Fail |
| 245 | + |
| 246 | +- Run tests individually to isolate issues |
| 247 | +- Check for API changes in updated packages |
| 248 | +- Review test framework compatibility (e.g., xUnit, NUnit versions) |
| 249 | + |
| 250 | +### CI/CD Pipeline Fails |
| 251 | + |
| 252 | +- Verify new SDK version is available in CI environment |
| 253 | +- Check `global.json` is in repo root (CI should respect it) |
| 254 | +- Update any hardcoded version references in pipeline |
| 255 | + |
| 256 | +## Key Resources |
| 257 | + |
| 258 | +- [**.NET Official Upgrade Guide**](https://learn.microsoft.com/en-us/dotnet/core/install/upgrade) |
| 259 | +- [**global.json Reference**](https://learn.microsoft.com/en-us/dotnet/core/tools/global-json) |
| 260 | +- [**AnalysisLevel Property**](https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#analysislevel) |
| 261 | +- [**ASP.NET Core Migration**](https://learn.microsoft.com/en-us/aspnet/core/migration/) |
| 262 | + |
| 263 | +## Examples by Scenario |
| 264 | + |
| 265 | +### Scenario 1: Simple Single-Project Upgrade |
| 266 | + |
| 267 | +For a single `.csproj` project: |
| 268 | + |
| 269 | +1. Update `<TargetFramework>net9.0</TargetFramework>` |
| 270 | +2. Run `dotnet build` |
| 271 | +3. Run `dotnet test` |
| 272 | +4. Commit with message: "Upgrade to .NET 9" |
| 273 | + |
| 274 | +### Scenario 2: Multi-Project Solution with CI/CD |
| 275 | + |
| 276 | +For solutions with multiple projects and GitHub Actions: |
| 277 | + |
| 278 | +1. Update all `.csproj` files in the solution |
| 279 | +2. Create/update `global.json` in solution root |
| 280 | +3. Update `.github/workflows/*.yml` to use new version |
| 281 | +4. Run full test suite locally: `dotnet test` |
| 282 | +5. Push and verify CI passes |
| 283 | +6. Commit message: "Upgrade solution to .NET 9 (includes CI/CD updates)" |
| 284 | + |
| 285 | +### Scenario 3: Gradual Multi-Version Support |
| 286 | + |
| 287 | +For libraries supporting multiple .NET versions: |
| 288 | + |
| 289 | +1. Update `<TargetFrameworks>net8.0;net9.0</TargetFrameworks>` |
| 290 | +2. Test on both versions: `dotnet test --framework net8.0 && dotnet test --framework net9.0` |
| 291 | +3. Document supported versions in README |
| 292 | +4. Gradually drop old version support in future releases |
| 293 | + |
0 commit comments