.Net Core migration problems

I am migrating my windows servers to Linux (see this thread). What I did so far:

  1. Changed all my own library projects to target .NET Standard 2.0
  2. Solved all issues with external libraries used in these DLLs (mainly I had issues with Log4Net because I am using a ColoredConsoleAppender which is not supported in their .NET core implementation. Adding a simple ConsoleAppender and adding some #ifdef pragmas did the trick.
  3. Built all my DLLs successfully targeting .NET Standard 2.0
  4. Tried to build my Windows Service with the new DLLs targeting .NET 4.6.1

The goal is to have all my DLLs running on Windows (targeting .NETStandard) before I port the EXE itself to .NET Core 2.0.

Problems
The Windows Service EXE targeting .NET 4.6.1 and referencing my DLLs targeting .NETStandard 2.0 throws strange errors:

Error    CS0012    The type 'IRedisClientsManager' is defined in an assembly that is not referenced. You must add a reference to assembly 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null'.

Error    CS0012    The type 'CredentialsAuthProvider' is defined in an assembly that is not referenced. You must add a reference to assembly 'ServiceStack, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null'.

Error    CS0012    The type 'IUserAuth' is defined in an assembly that is not referenced. You must add a reference to assembly 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null'.

What I do NOT understand is that it is asking for V 5.0.0.0 while I have installed in this project V 5.0.2!! This is the output of a Get-Package statement for the project containing the Windows EXE file targeting .NET 4.6.1:

ServiceStack                                      5.0.2  
ServiceStack.Api.Swagger                          5.0.2  
ServiceStack.Client                               5.0.2  
ServiceStack.Common                               5.0.2  
ServiceStack.Interfaces                           5.0.2  
ServiceStack.Redis                                5.0.2  
ServiceStack.Text                                 5.0.2  

I use ServiceStack 5.0.2 in ALL of my library projects. Here is a sample from one of them:

Id                        Version
--                        -------
ServiceStack.OrmLite.Core 5.0.2  
ServiceStack.Redis.Core   5.0.2  
ServiceStack              5.0.2  

Any idea what I am missing here???

Please see this answer:

My recommendation is to multi target your projects.

Hi Demis,
Does that mean you recommend to follow a project organisation as described in this Microsoft article? This would be true for ALL of my Library projects, correct?

Just to make sure I got it right: In my WPF clients I will reference ServiceStack.Client (using NuGet) and from my own DLLs containing DTO definitions etc I will use the version build against the “full .NET framework” (e.g. 4.6.1). The server which is .NET core and should execute in Docker4Linux I will reference the .NET core build of the same DLL(s), correct?

This is so complicated and has tons of limitations compared to Java…! All my hardware related libraries (using WMI) do NOT work on .NET core… I will have to replace them with Java Microservices; that works everywhere, Windoze, Linux, Mac, IBM mainframe!

It means you should maintain separate builds for projects you wish to run on .NET Core. With the new MSBuild system it effectively just means including both targets in your <TargetFrameworks/>, e.g:

Since most ServiceStack projects include both net45 and netstandard2.0 builds, both your project targets are able to use the same NuGet package reference, e.g:

<PackageReference Include="ServiceStack" Version="5.0.1" />

I understand the frustration, but given they’re targeting 2 completely different .NET runtimes the amount of effort to be able to create projects that run on both is quite minimal. Unfortunately the complexity of needing to understand what’s going on and why it’s needed leaks when you need to run on both.

If your end goal is to run on .NET Core I’d personally just port to that (and skip the multi targeting) and refactor out all the functionality that can’t run on .NET Core behind mockable interfaces that return test data. We skipped multi targeting when porting all our .NET Core Apps which were all pretty straight forward given we tend to only use ServiceStack deps, most of which supports .NET Core. So most of the existing source code was able to be used as-is.

The Service Gateway should also be able to help here. If you refactor your existing code-base to call InProcess Services for your Windows only functionality, your .NET Core code-base can use the same Gateway source code which instead of calling an InProcess Service, can be configured to call your remote .NET Framework Service.

Yeah if ever possible I like to avoid fiddling around with the .csproj files… The format of these files usually changes with new VS releases which may cause constant “headache” in the future. Also I do not like these compiler pragmas (#ifdefetc statements), they remind me too much to my C/C++ programming experience and are cluttering code files.

But I am not sure if a “.NET core only” aproach will work, since my clients are WPF and there will be some Angular based web clients in the future and some future servers will be written in Kotlin or Java.

Servers and clients share some DLLs (usually the <MyProject>.ServiceModel project of the server) as you described it here. So, if I got things right, I need to provide a “.NET Full” version of these assemblies for my WPF clients.

Or is ServiceStack reference a way around this also for C# WPF clients? (So far I thought it is for use with other languages only…) And does this work with .NET core servers?

However if anybody needs to go the path of multi-targeting, I found a good and very detailed article about Multi-Targeting from Rick Strahl.

The WPF App needs to remain a .NET Framework project but will still be able to use Add ServiceStack Reference feature from a .NET Core Server - the generated DTOs remain identical.

1 Like