Upgrading from .NET Framework to .NET 6 is possible via assistants, in this article we are exploring the .NET Upgrade Assistant provided by Microsoft. This is part 2 of 2 in this series.
Microsoft provides a command-line tool1 to assess .NET Framework apps. It provides an analysis report for each of the projects in the solution containing details on:
- Package dependencies that need to be removed/added/upgraded.
- References that need to be removed/added/upgraded.
- Framework References that need to be removed/added/upgraded.
- Call out if there is a package upgrade across major versions that could lead towards breaking changes.
- Unsupported API used in the projects with pointers to a recommended path forward if one is available.
Similarly to the Porting Assistant, the tool is not going to do magical things but will help you to identify critical points in the solution that need to be reviewed.
Supported project types and languages
It is worth mentioning that the tool supports the following project types:
- ASP.NET MVC
- Windows Forms
- Windows Presentation Foundation (WPF)
- Console app
- UWP to Windows App SDK (WinUI)
- Xamarin.Forms to .NET MAUI
The tool supports C# and Visual Basic projects.
Do you remember ASP.NET MVC? The sample available https://github.com/aspnet/samples/tree/main/samples/aspnet/MVC/EnumSample.
Interestingly enough this solution works on .NET Framework 4.5, but I didn't dare to install it on my current machine, so I manually tweaked the Project file to .NET Framework 4.8.
I recommend a separate machine, probably a VM to run this sort of exercise.
If you are in Visual Studio 2022 you get this warning.
As you do the framework change, it modifies the project Target Framework:
If you run the Enum project, it will work:
There are some prerequisites before installing the Upgrade tool. Make sure you install the upgrade assistant:
dotnet tool install -g --add-source "https://api.nuget.org/v3/index.json" --ignore-failed-sources upgrade-assistant
Run the analyzer to verify the solution on .NET 6:
upgrade-assistant analyze --target-tfm-support LTS <Path to csproj or sln to upgrade>
From here we can see there will be some hiccups.
Full usage information:
Usage: upgrade-assistant analyze [options] <project> Arguments: <project> Options: --extension <extension> Specifies a .NET Upgrade Assistant extension package to include. This could be an ExtensionManifest.json file, a directory containing an ExtensionManifest.json file, or a zip archive containing an extension. This option can be specified multiple times. -v, --verbose Enable verbose diagnostics --target-tfm-support <Current|LTS|Preview> Select if you would like the Long Term Support (LTS), Current, or Preview TFM. See https://dotnet.microsoft.com/platform/support/policy/dotnet-core for details for what these mean. --format <HTML> Specify the format in which the analysis report will be generated. Currently supports html other than the default SARIF format. --version Show version information -?, -h, --help Show help and usage information
I have both .NET 6 and .NET 7 available in my machine, but I enforced .NET 6 LTS to be used with --target-tfm-support
The default output produced will be a file of type .SARIF format, which can be opened on VStudio Code via extension:
Run the analyzer to upgrade the solution on .NET 6:
upgrade-assistant upgrade --target-tfm-support LTS --non-interactive <Path to csproj or sln to upgrade>
If you want an automated way of upgrading all the projects, make sure to set
--non-interactive when running the tool.
The output is verbose:
Full usage information:
Usage: upgrade-assistant upgrade <project> [command] [options] Arguments: <project> The path to a project or solution file to be used. Options: -x, --extension <extension> Specifies a .NET Upgrade Assistant extension package to include. This could be an ExtensionManifest.json file, a directory containing an ExtensionManifest.json file, or a zip archive containing an extension. This option can be specified multiple times. -o, --option <option> Specifies an option that should be added to Upgrade Assistant that may be used by extensions. -e, --entry-point <entry-point> Provides the entry-point project to start the upgrade process. This may include globbing patterns such as '*' for match. -i, --ignore-unsupported-features Acknowledges that upgrade-assistant will not be able to completely upgrade a project. This indicates that the solution must be redesigned (e.g. consider Blazor to replace Web Forms). --vs-path <vs-path> Path to a VS install directory to be used for %VSINSTALLDIR%. If not provided, the latest installed version will be used. --msbuild-path <msbuild-path> Path to a MSBuild install directory to be used. If not provided, the latest installed version will be used. -t, --target-tfm-support <LTS|Preview|STS> Select if you would like the Long Term Support (LTS), Standard Term Support (STS), or Preview TFM. See https://dotnet.microsoft.com/platform/support/policy/dotnet-core for details on what these mean. -v, --verbose Enable verbose diagnostics -f, --format <format> Specify format of analyze result. If not provided, a sarif file will be produced. Available default values: "sarif", "html" --skip-backup Disables backing up the project. This is not recommended unless the project is in source control since this tool will make large changes to both the project and source files. --non-interactive Automatically select each first option in non-interactive mode. --non-interactive-wait <non-interactive-wait> Wait the supplied seconds before moving on to the next option in non-interactive mode. -?, -h, --help Show help and usage information Commands: list-formats
The same .SARIF report is created at the end of processing on a file called
The new upgraded solution
So the solution was migrated from .NET Framework 4.8 to .NET 6, but will it work?
Similar to the previous article, the solution will not even compile. This will give you an idea of the efforts required, so you can provide estimates, and get the team to work on it.
A lot is going on in this MVC project, as you can see in the
csproj below. A good approach in this case would be to start a new project and move files across.
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <OutputType>Exe</OutputType> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> <RestorePackages>true</RestorePackages> </PropertyGroup> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <OutputPath>bin\</OutputPath> </PropertyGroup> <ItemGroup> <Compile Update="Global.asax.cs"> <DependentUpon>Global.asax</DependentUpon> </Compile> </ItemGroup> <ItemGroup> <None Include="Web.Debug.config"> <DependentUpon>Web.config</DependentUpon> </None> <None Include="Web.Release.config"> <DependentUpon>Web.config</DependentUpon> </None> </ItemGroup> <ItemGroup> <Folder Include="App_Data\" /> </ItemGroup> <ItemGroup> <PackageReference Include="bootstrap" Version="3.2.0" /> <PackageReference Include="jQuery" Version="2.1.1" /> <PackageReference Include="jQuery.Validation" Version="1.13.0" /> <PackageReference Include="Microsoft.jQuery.Unobtrusive.Validation" Version="3.2.3" /> <PackageReference Include="Modernizr" Version="2.8.3" /> <PackageReference Include="Respond" Version="1.4.2" /> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> <PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" /> <PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" /> <PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.355802"> <PrivateAssets>all</PrivateAssets> </PackageReference> <PackageReference Include="EntityFramework" Version="6.4.4" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.11" /> </ItemGroup> </Project>
This is a great tool, that will help to point out the issues ahead of time during upgrades.
I tried using the HTML format when generating the report output, but the HTML is too simple and it doesn't allow interactions, but the .SARIF extension on VStudio Code works much better, as you can drill down to the issues dynamically.
If I was to upgrade a single project, rather than do it
non-interactively, I would go one step at a time as the tool asks for you to take decisions. This is much more verbose, but it gives you a better understanding of what the tool is trying to do.
.NET 6 Upgrade - Part 2 - .NET Upgrade Assistant