Migrating Service Fabric apps to .NET 6
Tags: azure, servicefabric, dotnet, upgrade
Published: 2023-04-10 10:01:54

---
title: Migrating Service Fabric apps to .NET 6
description: There's more to do than just flipping the target framework to .NET 6 when migrating Service Fabric apps
slug: migrate-sf-to-net6
published: true
date: 2023-04-10 09:11:46 UTC
tags: azure, servicefabric, dotnet, upgrade
canonical_url: https://kosalanuwan.hashnode.dev/migrate-sf-to-net6
cover_image: https://user-images.githubusercontent.com/958227/233758742-f004ed33-4e33-423d-8858-b1f0f9768ed4.jpeg?auto=compress
---

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](https://youtu.be/LjClUEu9duk?t=2207) 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](https://user-images.githubusercontent.com/958227/230864432-7ee6a01a-e105-41a2-abd7-6779e6068b65.gif?auto=compress)

The Alertbox Inc. (@[alertbox](/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](https://devblogs.microsoft.com/devops/upgrade-of-net-agent-for-azure-pipelines), so they have no way of running pipelines without [adding the UseDotNet task to select what .NET version is to use](/kosalanuwan/selecting-what-net-version-is-to-use-14n1) 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](https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-get-started). And that means runtime, SDK, and the tools to [create, build, and run reliable service apps on a local cluster](https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-quick-start#create-a-stateless-service). Unfortunately, [the IIS team recently sunset the Web PI](https://blogs.iis.net/iisteam/web-platform-installer-end-of-support-feed), 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](/kosalanuwan/selecting-what-net-version-is-to-use-14n1) that is in.

```bash
#!/bin/zsh
# Show installed SDKs.
dotnet --list-sdks
# Add a global.json file
dotnet new globaljson --sdk-version 6.0.403
```

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](https://github.com/microsoft/service-fabric/issues/1290#issuecomment-1489868105) yet. I can [create a new reliable service app on .NET 6](https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-quick-start#create-a-stateless-service) 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](https://github.com/microsoft/service-fabric/issues/885) with a bunch of _.xml_ files for configuration but with no C# code. They require [_Fabric.MSBuild_ nuget](https://www.nuget.org/packages/Microsoft.VisualStudio.Azure.Fabric.MSBuild) 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.

```xml
<!-- packages.config -->
<package id="Microsoft.VisualStudio.Azure.Fabric.MSBuild"
         version="1.7.7"
         targetFramework="net48" />
```

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](https://github.com/search?q=org%3Adotnet+%3CTargetFrameworks%3E+language%3AXML&type=code&l=XML), 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.

```bash
#!/bin/zsh
# First restore packages
dotnet restore && \
# Then scan for outdated packages
dotnet list package --outdated
```

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

```bash
#!/bin/zsh
dotnet add package Azure.Messaging.ServiceBus
```

It's slightly obnoxious that they only let you check for the status, so I'm going to have to [upgrade outdated packages](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-add-package#examples) 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 <mark>demands highly intense concentration on breaking changes</mark> 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](https://user-images.githubusercontent.com/958227/230875800-623ebd14-efb0-4bf3-9887-63f5f4329a8d.gif?auto=compress)

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.](https://github.com/microsoft/service-fabric/issues/1356) 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,](https://github.com/microsoft/service-fabric/issues/1356#issuecomment-1362622324) but the .NET runtime team has [turned off metadata generation for dynamic classes](https://github.com/dotnet/runtime/issues/62977#issuecomment-1186149824) 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](https://github.com/dotnet/runtime/pull/77322), so a little `winget install` magic is all that's necessary to update the .NET 6 installed locally.

```bash
#!/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
```

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

```json
// global.json
{
  "sdk": {
    "version": "6.0.407",
    "allowPrerelease": false,
    "rollForward": "latestMinor"
  }
}
```

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](/kosalanuwan/selecting-what-net-version-is-to-use-14n1). 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