Upgrade your .Net Core Service Fabric Microservices from VS 2015 to VS 2017

Service Fabric projects have evolved at what feels like a cracking pace, along with the .Net Core platform and tooling, and with the recent release of Visual Studio 2017 no doubt you are considering the productivity merits of upgrading (container support). For Service Fabric projects designed in Visual Studio 2015 and using the .Net Core .xproj/project.json structures now deprecated in Visual Studio 2017, the automatic upgrade process may result in only partial conversion success.

In this article we’ll take a look at the issues encountered while upgrading a .Net Core Service Fabric solution containing 77 .xproj/project.json projects to Visual Studio 2017.

From .Net Core Visual Studio 2015 .xproj/project.json to Visual Studio 2017 .csproj

To begin, let’s take a look at a simplified example of a stateful .Net Core microservice defined with the following project.json (VS 2015) structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"title": "Acme.Service.Auction",
"description": "Acme.Service.Auction",
"version": "1.0.0-*",

"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true,
"compile": {
"exclude": [
"PackageRoot"
]
}
},

"dependencies": {
"Microsoft.ServiceFabric": "5.1.150",
"Microsoft.ServiceFabric.Services": "2.1.150",
"EnterpriseLibrary.SemanticLogging": "2.0.1406.1"
},

"frameworks": {
"net46": {}
},

"runtimes": {
"win7-x64": {}
}

}

Once the automatic Visual Studio 2017 conversion completes, you’ll end up with a .csproj file similar to the below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Description>Acme.Service.Auction</Description>
<AssemblyTitle>Acme.Service.Auction</AssemblyTitle>
<TargetFramework>net46</TargetFramework>
<PreserveCompilationContext>true</PreserveCompilationContext>
<AssemblyName>Acme.Service.Auction</AssemblyName>
<OutputType>Exe</OutputType>
<PackageId>Acme.Service.Auction</PackageId>
<RuntimeIdentifiers>win7-x64</RuntimeIdentifiers>
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<IsServiceFabricServiceProject>True</IsServiceFabricServiceProject>
</PropertyGroup>

<ItemGroup>
<Compile Remove="PackageRoot\**\*" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ServiceFabric" Version="5.1.150" />
<PackageReference Include="Microsoft.ServiceFabric.Services" Version="2.1.150" />
<PackageReference Include="EnterpriseLibrary.SemanticLogging" Version="2.0.1406.1" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>

</Project>

Processor architecture mismatch warnings

If you compile the above project, in the build output window you may notice processor architecture mismatch warnings, for example:

1>C:\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(1964,5): warning MSB3270: There was a mismatch between the processor architecture of the project being built "MSIL" and the processor architecture of the reference "C:\Users\Admin\.nuget\packages\microsoft.servicefabric.services\2.1.150\lib\net45\Microsoft.ServiceFabric.Services.dll", "AMD64". This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project through the Configuration Manager so as to align the processor architectures between your project and references, or take a dependency on references with a processor architecture that matches the targeted processor architecture of your project.

To fix these and similar processor architecture mismatch warnings, replace:

1
<RuntimeIdentifiers>win7-x64</RuntimeIdentifiers>

With this (there is no ending s):

1
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>

Packaging and Publishing… not so fast!

So the converted microservice now compiles without any warnings, what’s all the fuss about… well if you now attempt to package and publish this microservice to Service Fabric, it fails with a message similar to the below:

C:\AcmeAuctions\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.6.0\build\Microsoft.VisualStudio.Azure.Fabric.Application.targets(248,5): warning MSB3026: Could not copy "C:\AcmeAuctions\src\Acme.Service.Auction\bin\x64\Debug\net46\win7-x64\Acme.Service.Auction.runtimeconfig.json" to "C:\AcmeAuctions\pkg\Debug\Acme.Service.AuctionPkg\Code". Beginning retry 1 in 1000ms. Could not find a part of the path 'C:\AcmeAuctions\pkg\Debug\Acme.Service.AuctionPkg\Code'.

Cross checking various existing github and stackoverflow issues, the current Service Fabric SDK for VS 2017 and msbuild tooling appear not support .Net Core projects for Actor, Stateful and Stateless services defined with Microsoft.NET.Sdk. To clarify, the tooling supports Stateful and Stateless ASP.Net Core service projects only, however I prefer all projects to be in .Net Core, not just my ASP.Net microservices. Hence I replace this:

1
<Project Sdk="Microsoft.NET.Sdk">

With the below; as I expect the above scenario to be resolved in the near future with a SDK and tooling update. I’ve simply switched to a supported Service Fabric and VS 2017 template scenario which is to define all microservice .csproj files using Microsoft.NET.Sdk.Web:

1
<Project Sdk="Microsoft.NET.Sdk.Web">

With this simple change your Service Fabric microservies will support .Net Core Actor, Stateful and Stateless VS 2017 projects and will package and publish normally. Note that in Visual Studio 2017 the project icon will change to a web project, and you may optionally want to git ignore and exclude launchSettings.json files, however given the non-intrusive workaround I believe it’s well worth it. To remove the launchSettings.json file from your project, modify the ItemGroup to:

1
2
3
4
<ItemGroup>
<Compile Remove="PackageRoot\**\*" />
<Content Remove="Properties\launchSettings.json" />
</ItemGroup>

Summary

We’ve looked at some simple changes you can make to your converted and upgraded Service Fabric project files. The changes allow you to write your Actor, Stateful and Stateless services in .Net Core while taking advantage of the great new productivity gains (Azure integration, Docker support etc.) offered by Visual Studio 2017 and Service Fabric!

In our next article we’ll continue the upgrade journey by walking through a few DevOps limitations encountered while reconfiguring a Service Fabric Visual Studio Team Services CI/CD pipeline.