Mess in ServiceStack version 5

2019-07-23 13:03发布

问题:

I have a ASP.NET Core application hosted in Windows Sercice, so it is a .NETCore project but TargetFramework is .NET Framework. This Microsoft document describes this kind of project.

The application works fine with SerciceStack.Core 1.0.44, here goes the snippet of my project file.

<PackageReference Include="ServiceStack.Core" Version="1.0.44" />
<PackageReference Include="ServiceStack.Kestrel" Version="1.0.44" />
<PackageReference Include="ServiceStack.Text.Core" Version="1.0.44" />
<PackageReference Include="ServiceStack.Api.Swagger.Core" Version="1.0.44" />

Now I am trying to upgrade to version 5.0.2, then I found there are two families of assemblies. ServiceStack 5.0.2 and ServiceStack.Core 5.0.2

Then I tried to head on ServiceStack.Core 5.0.2 direction and found it is totally a mess.

First, there is no ServiceStack.Api.Swagger.Core 5.0.2, the only one is ServiceStack.Api.Swagger 5.0.2 and it is depending on ServiceStack 5.0.2.

Second, ServiceStack.Kestrel 5.0.2 dependencies are in different family of ServiceStack.Kestrel 1.0.44. You can compare the dependencies by opening the links.

  • ServiceStack.Kestrel 1.0.44 depends on ServiceStack.Core 1.0.44;
  • ServiceStack.Kestrel 5.0.2 depends on ServiceStack 5.0.2

So ServiceStack.Kestrel 5.0.2 cannot be used with ServiceStack.Core 5.0.2 any more.

Then I tried the other direction ServiceStack 5.0.2 -- changing all references to the one without Core postfix and encountering another issue.

Which direction should I go in my case?

Best Regards

回答1:

Please read the Run ASP.NET Core Apps on the .NET Framework docs. You must continue to reference the .Core packages as they only contains .NET Standard 2.0 builds. Referencing the main packages without the .Core suffix e.g. ServiceStack in a .NET Framework project will reference the net45 builds which can only run classic ASP.NET Framework or HttpListener Apps.

In a .NET Core App you should reference the main NuGet packages e.g. ServiceStack as it will ignore the net45 builds and only reference the .NET Standard 2.0 builds.



回答2:

Finnally I get the existing project working with version 5.

First, upgrade the version to 5 as below.

<PackageReference Include="ServiceStack.Api.Swagger" Version="5.0.2" />
<PackageReference Include="ServiceStack.Client.Core" Version="5.0.2" />
<PackageReference Include="ServiceStack.Common.Core" Version="5.0.2" />
<PackageReference Include="ServiceStack.Core" Version="5.0.2" />
<PackageReference Include="ServiceStack.Interfaces.Core" Version="5.0.2" />
<PackageReference Include="ServiceStack.Kestrel" Version="5.0.2" />
<PackageReference Include="ServiceStack.Text.Core" Version="5.0.2" />

Then there are a lot of compilation errors as below.

error CS0433: The type 'IRequest' exists in both 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null' and 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587'
error CS0433: The type 'IRequest' exists in both 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null' and 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587'
error CS0433: The type 'IReturn<T>' exists in both 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null' and 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587'
error CS0433: The type 'Service' exists in both 'ServiceStack, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null' and 'ServiceStack, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587'
error CS0433: The type 'RouteAttribute' exists in both 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null' and 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587'
error CS0246: The type or namespace name 'Verbs' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'Summary' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'Notes' could not be found (are you missing a using directive or an assembly reference?)
error CS0433: The type 'ApiMemberAttribute' exists in both 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null' and 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587'
error CS0246: The type or namespace name 'Name' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'ParameterType' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'DataType' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'IsRequired' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'Description' could not be found (are you missing a using directive or an assembly reference?)
error CS0433: The type 'IReturn<T>' exists in both 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null' and 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587'
error CS0433: The type 'ApiMemberAttribute' exists in both 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null' and 'ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587'
error CS0246: The type or namespace name 'Name' could not be found (are you missing a using directive or an assembly reference?)
warning MSB3243: No way to resolve conflict between "ServiceStack, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null" and "ServiceStack, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587". Choosing "ServiceStack, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null" arbitrarily.
warning MSB3243: No way to resolve conflict between "ServiceStack.Client, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null" and "ServiceStack.Client, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587". Choosing "ServiceStack.Client, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null" arbitrarily.
warning MSB3243: No way to resolve conflict between "ServiceStack.Common, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null" and "ServiceStack.Common, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587". Choosing "ServiceStack.Common, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null" arbitrarily.
warning MSB3243: No way to resolve conflict between "ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null" and "ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587". Choosing "ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null" arbitrarily.
warning MSB3243: No way to resolve conflict between "ServiceStack.Text, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null" and "ServiceStack.Text, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587". Choosing "ServiceStack.Text, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null" arbitrarily.

These errors are caused by ServiceStack.Api.Swagger and ServiceStack.Kestrel. In previous version, they depend on ServiceStack.Core whose publicKeyToken is null; but in this new version, they depend on ServiceStack whose publicKeyToken exists.

Binding redirection cant help in this case because publicKeyToken is null.

Eventually ServiceStack and ServiceStack.Core they have the same implementation on Windows in my case.

Hence, the key to solve this issue is to change the dependencies of ServiceStack.Api.Swagger and ServiceStack.Kestrel from ServiceStack family to ServiceStack.Core family.

The first step is to copy the assembly files into a packages folder in project and change the reference manner from PackageReference to Reference. After that, NuGet doesnt manage them any more and we can modify the assembly.

Now compiling the project results in different errors like below.

Error   CS0012  The type 'IPlugin' 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=02c12cbda47e6587'.  
Error   CS0012  The type 'IPreInitPlugin' 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=02c12cbda47e6587'.

They are generated by ServiceStack.Api.Swagger because it is trying to link to the type in ServiceStack. In fact the same type exists in ServiceStack.Core assembly whose publicKeyToken is null.

Now I take use of the tool reflexil to edit ServiceStack.Api.Swagger.dll

Select ServiceStack dependencies and clear their publicKeyToken as it is presented in screenshot above.

Compile and now everything works and I dont change any code.

The root issue is that ServiceStack changes the dependencies from ServiceStack.Core family to ServiceStack family.

Personally I would suggest ServiceStack release another parallel package ServiceStack.Api.Swagger.Core 5.0.2 which depends on ServiceStack.Core.