DEV Community

Cover image for Migrating Service Fabric apps to .NET 6
Kosala (Nuwan) Perera
Kosala (Nuwan) Perera

Posted on • Originally published at kosalanuwan.hashnode.dev on

Migrating Service Fabric apps to .NET 6

Migrating Service Fabric apps to the .NET 6 suck! Not only is there no opensource community engagement, but there's no same-day support for new .NET versions at all. What a SHAM! There's nothing I can do about that.

2013-06-13_frustration_obliviousness_sales personnel_software_third party library_new version_windows_engineering

The Alertbox Inc. (@alertbox) pipelines page is open on my work PC and one of the CI pipelines is broken. For the record, Alertbox has ~60 microservices. They require Service Fabric / .NET Core combo to build and release. I'm going to go ahead and say that they use windows-latest on hosted agents. And the Azure Pipelines team is upgrading the .NET used by agents, so they have no way of running pipelines without adding the UseDotNet task to select what .NET version is to use in the pipeline agents. Maybe that's a plausible fix, but they recommend keeping the source code up-to-date with the current LTS version of .NET. So what does each microservice have that must be upgraded for .NET 6?

Service Fabric app

The first thing we're going to need is the latest update for Service Fabric. And that means runtime, SDK, and the tools to create, build, and run reliable service apps on a local cluster. Unfortunately, the IIS team recently sunset the Web PI, so the Service Fabric team bundled the latest releases with Visual Studio, and I'm going to have to update Visual Studio to download them for me.

The other thing we're going to need is a global.json file since there are several .NET versions installed already in my work PC, so it's definitely necessary to break out that dotnet driver and create a global.json file to select net6.0 SDK version that is in.

#!/bin/zsh
# Show installed SDKs.
dotnet --list-sdks
# Add a global.json file
dotnet new globaljson --sdk-version 6.0.403
Enter fullscreen mode Exit fullscreen mode

I'm a bit of a control freak, not gonna lie. I like the idea of knowing what's happening underneath. It's slightly obnoxious that Service Fabric project templates are not opensourced yet. I can create a new reliable service app on .NET 6 to figure out what's new in the scaffolding project.

The first on the list is the entry project .sfproj. They use a non-SDK-style project template with a bunch of .xml files for configuration but with no C# code. They require Fabric.MSBuild nuget to build and package Service Fabric apps. Unfortunately, the dotnet add package command won't update dependencies since they only support <PackageReference /> and non-SDK-style project template uses the package.config file to manage dependencies.

<!-- packages.config -->
<package id="Microsoft.VisualStudio.Azure.Fabric.MSBuild"
         version="1.7.7"
         targetFramework="net48" />
Enter fullscreen mode Exit fullscreen mode

I can update the package.config to use the latest versions but there's more to do. The .sfproj still points to the older build tools. And you do want to use the latest version to build and package.

Updating the .sfproj is extraordinarily uncomplicated. All we need to do is figure out the references to the Fabric.MSBuild package and replace the version numbers, say, find all and replace the version number to 1.7.7 from the version that is already been used. Then I can replace the <TargetFrameworkVersion /> version with the .NET Framework 4.8 and we're done.

The .xml configurations need no changes, so we can ignore them for now.

Services and dependencies

Next on the list are reliable services. This covers a lot of ground since Alertbox uses multiple stateless services bundled into a single Service Fabric app, say, Web APIs and Console apps, and they target netcoreapp3.1 to build and run, so we're going to have to upgrade them to net6.0. I can replace <DefaultNetCoreTragetFramework /> in the Directory.Build.props file like they do on @dotnet repos on GitHub, but there's more to it. They need to upgrade dependencies.

Figuring out dependencies to upgrade for all the .csproj projects that are in the code repo is basically the same as listing installed SDKs.

#!/bin/zsh
# First restore packages
dotnet restore && \
# Then scan for outdated packages
dotnet list package --outdated
Enter fullscreen mode Exit fullscreen mode

I can check and review each package to decide whether or not to upgrade.

#!/bin/zsh
dotnet add package Azure.Messaging.ServiceBus
Enter fullscreen mode Exit fullscreen mode

It's slightly obnoxious that they only let you check for the status, so I'm going to have to upgrade outdated packages one at a time, say, migrating Web APIs and the Automapper configurations to the latest versions by going thru what's new and migration docs. It's taking a few tries to get the unit tests green since it demands highly intense concentration on breaking changes of each package upgrade.

Troubleshooting

Visual Studio can build from source but it keeps failing to deploy the Service Fabric app onto the local cluster. I'm going to go ahead and say that they use Deploy-FabricApplication.ps1 powershell script in the .sfproj to deploy, so replacing it from the script in that new boilerplate code to take care of it seems like the right answer.

2010-08-21_product safety testing_angry_rodney_swear_ship_bandage

Then I can build and run the app from source and Visual Studio will do the rest for me. But there are more problems.

The Visual Studio debugger won't attach. This may be difficult. I'll come back to this later.

This may not be an issue with Service Fabric since it works on my colleague's PC, so it's definitely necessary to diff both development environments to figure out what SDK version to use.

Service Fabric creates dynamic proxy classes for service remoting, but the .NET runtime team has turned off metadata generation for dynamic classes in .NET 6, so it would be impossible to tell Visual Studio debugger how to load metadata for dynamic proxy classes that Service Fabric creates. The .NET team has a release that always generates metadata, so a little winget install magic is all that's necessary to update the .NET 6 installed locally.

#!/bin/zsh
# Display the status of the installed SDK.
dotnet sdk check
# Install/upgrade the SDK via Windows Package Manager.
winget install Microsoft.DotNet.SDK.6
# Show installed SDKs.
dotnet --list-sdks
Enter fullscreen mode Exit fullscreen mode

But there's more to do. We need to update the global.json with the new SDK version.

// global.json
{
  "sdk": {
    "version": "6.0.407",
    "allowPrerelease": false,
    "rollForward": "latestMinor"
  }
}
Enter fullscreen mode Exit fullscreen mode

Then I can build and run from source and Visual Studio debugger will do the rest for me. And if version >=6.0.407 is not installed locally, nothing gets compiled.

Pipelines

I'm not exactly sure when the Azure Pipelines team is going to remove .NET 6 once it reaches end-of-life support, so I'm going to have to update the build steps to always select the .NET version used in the code repo. All I need to do is push all changes to a feature branch to raise a pull request and the branch policies will trigger the CI pipeline for me. Excellent!

/KP

Top comments (0)