Why does dotnet publish not publish the versions expected? - c#

Dealing with CVE-2018-8409, noted that our dotnet publish (.NET Core 2.1.403 ASPNET Core app) is publishing v4.0.0.1 of System.IO.Pipelines.dll in our output directory.
I added a nuget package reference to v4.5.3 of System.IO.Pipelines.
I see no reference to v4.0.0.1 in the build output, aside from this:
Unified primary reference "System.IO.Pipelines, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51".
Using this version instead of original version "4.0.0.0" in "<home_dir>\.nuget\packages\microsoft.aspnetcore.connections.abstractions\2.1.3\lib\netstandard2.0\Microsoft.AspNetCore.Connections.Abstractions.dll" because AutoUnify is 'true'.
Using this version instead of original version "4.0.0.0" in "<home_dir>\.nuget\packages\microsoft.aspnetcore.http.connections\1.0.4\lib\netstandard2.0\Microsoft.AspNetCore.Http.Connections.dll" because AutoUnify is 'true'.
Using this version instead of original version "4.0.0.0" in "<home_dir>\.nuget\packages\microsoft.aspnetcore.server.kestrel.core\2.1.3\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Core.dll" because AutoUnify is 'true'.
Using this version instead of original version "4.0.0.0" in "<home_dir>\.nuget\packages\microsoft.aspnetcore.server.kestrel.transport.abstractions\2.1.3\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll" because AutoUnify is 'true'.
Using this version instead of original version "4.0.0.0" in "<home_dir>\.nuget\packages\microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.3\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll" because AutoUnify is 'true'.
Using this version instead of original version "4.0.0.0" in "<home_dir>\.nuget\packages\microsoft.aspnetcore.signalr.core\1.0.4\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Core.dll" because AutoUnify is 'true'.
Resolved file path is "<home_dir>\.nuget\packages\system.io.pipelines\4.5.3\lib\netstandard2.0\System.IO.Pipelines.dll".
Reference found at search path location "{HintPathFromItem}".
This reference is not "CopyLocal" because at least one source item had "Private" set to "false" and no source items had "Private" set to "true".
The ImageRuntimeVersion for this reference is "v4.0.30319"
NOTE : <home_dir> is my user directory, it's not actually part of the output, fyi.
Yet when I check in VS2017, I clearly see that the nuget package says System.IO.Pipelines (4.5.3)
I'm expecting that System.IO.Pipelines 4.5.3 would be in the output, including any necessary assembly binding redirects.
Any ideas what I'm missing?
Thanks!

In an extremely annoying move, further analysis has revealed to me that nuget package 4.5.3, contains assembly version 4.0.0.1
Whyyyyyyy Microsoft, Whyyyyyyy

Related

How does csc/Roslyn resolve assembly version?

I have a console program that has two direct dependencies: ClosedXML v0.97 and ClosedXML.Report 0.2.4. The ClosedXML.Report dependency also depends on ClosedXML, but in a version 0.95.
When I try to compile the program in NET6 (basically only a reference to a class in the ClosedXml.Report),
_ = new XLTemplate(new System.IO.MemoryStream());
I get a compiler error
CS0012 The type 'IXLWorkbook' is defined in an assembly that is not referenced. You must add a reference to assembly 'ClosedXML, Version=0.95.0.0, Culture=neutral, PublicKeyToken=null'.
Why doesn't csc.exe recognize the 0.97 version to use and requests 0.95 (the indirect dependency)? The assembly version of package is same as the nuget version.
Nuget uses direct-dependency-wins mechanism and I though .net core also uses that for assemlby resolution. Is a mechanism different? How does roslyn resolve which version to use and when to throw an error?
Relevant piece of MSBuild
C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\Roslyn\csc.exe
/reference:C:\Users\username\.nuget\packages\closedxml\0.97.0\lib\netstandard2.0\ClosedXML.dll
/reference:C:\Users\username\.nuget\packages\closedxml.report\0.2.4\lib\netstandard2.0\ClosedXML.Report.dll
One possible explanation for this behavior would be if IXLWorkbook, which is apparently required by the call to new XLTemplate() no longer exists in Version 0.97 of ClosedXML.
If possible, try to rebuild ClosedXML.Report with ClosedXML 0.97. Since these apparently are early versions (Version < 1.0) breaking changes between versions seem possible. Also, can you make sure that the output bin directory actually contains Version 0.97?

Nuget PackageReference fails to manage multiple versions of sub dependency

Context
I have an application which has a dependency graph which looks like...
My Application
Dependency1 v1.0
Microsoft.Extensions.Configuration.Abstractions v5.0
Dependency2 v3.1.22
Microsoft.Extensions.Configuration v3.1.22
Microsoft.Extensions.Configuration.Abstractions v3.1.22
Aka, two different dependencies rely on Microsoft.Extensions.Configuration.Abstractions. All dependencies are minimum versions, and are indicated as allowing higher versions. Seemingly, both should accept v5.0.
Nuget correctly picks version 5.0 as the version of the dll it put out in the bin folder. But, at runtime, when My Application tries to use Dependency2, it throws an exception:
Could not load file or assembly 'Microsoft.Extensions.Configuration.Abstractions, Version=3.1.22.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.
What I've tried
Installing Microsoft.Extensions.Configuration.Abstractions v5.0 explicitly
This made the dependency graph look like:
My Application
Dependency1 v1.0
Microsoft.Extensions.Configuration.Abstractions v5.0
Dependency2 v3.1.22
Microsoft.Extensions.Configuration v3.1.22
Microsoft.Extensions.Configuration.Abstractions v3.1.22
Microsoft.Extensions.Configuration.Abstractions v5.0
and otherwise changed nothing. Still get the exception.
Downgrading Dependency1 to use an older version
I had a similar issue with another dependency, and resolved that by lowering the version of the dependencies until their subdependencies' versions matched.
However, Dependency1 does not have an older version that relies on Microsoft.Extensions.Configuration.Abstractions 3.1.22, so I could not do the same on this one.
Nor can I upgrade Dependendency2 to a newer version that relies on Microsoft.Extensions.Configuration.Abstractions 5.0, because then it breaks the other one I already fixed.
Setting the DependencyVersion behavior on Dependency2 to Highest instead of Lowest
The answers on this question suggested setting the DependencyVersion behavior on Dependency2 to Highest.
I did not have the UI option described in that question, so instead I ran this command in the PackageManagerConsole
Install-Package Dependency2 -Version 3.1.22 -DependencyVersion Highest
This seemingly made no difference. It still throws the exception, but also I'm not seeing any feedback that suggests the DependencyVersion was changed for that particular dependency. I'm not sure if I missed the place to check that, or if the DependencyVersion is just not available for PackageReference projects, but I'm not sure what else to try.
I am at the limit of things I can find to try. Is there a way to tell .NET which version of Microsoft.Extensions.Configuration.Abstractions to use explicitly, for all dependencies? Or something similar to Package.config's binding redirects that let you roll old versions of packages into new versions, but for PackageReference?

Nuget package references cause "Could not load file or assembly" ?

There is a recent principle on Nuget package parsing. For details, see how NuGet parses package dependencies. A Microsoft diagram is used to explain:
This time you will choose the most recent package, which is the 2.0 version.
no problem.
One problem I encountered today is that one of my Nuget packages (called Package A current version 1.2.3) originally only supports the version of netstandard 2.0, which is defined in the csproj file.
<TargetFramework>netstandard2.0</TargetFramework>
I have another product, the ECS Nuget package (called Package B version 1.0.0), and Package B needs to reference Package A.
The relationship route is [Package B 1.0.0] -> [Package A 1.2.3]
At this time, the two packages in the program can be used normally.
Later, due to the support of the .net framework, I modified the original package A nuget package and changed it to the following.
<TargetFrameworks>netstandard2.0;net45</TargetFrameworks>
Package A package generation version is 1.3.2. At this time, I refer to the above two packages and find that the compilation is ok, but I am getting an error at runtime.
I can solve the above problem by upgrading Package B, but why is this error?
Is it because of the use of TargetFrameworks?
I also hope that the big men will give pointers.
When I compare the *.deps.json file, I found something helpful. Here is the first scenario get the following json file:
"aliyun-net-sdk-core/1.3.2": {
"dependencies": {
"Serilog": "2.5.0",
"Serilog.Exceptions": "4.0.0",
"Serilog.Sinks.File": "4.0.0"
},
"runtime": {
"lib/netstandard2.0/aliyun-net-sdk-core.dll": {
"assemblyVersion": "0.0.0.0",
"fileVersion": "0.0.0.0"
}
}
}
Because of the reference to version 1.3.2, however, the CLR can't find the DLL with Version 1.3.2 when loading the assembly, there is only assembly version 0.0.0.0, so the CLR looks for the 1.2.3 version referenced by the original project, but it is not found, so it reports an error.
Clearly understood.
After I make up the miss assembly version of the project, I got the
right result.

Program is referring to a different version of Newtonsoft.JSON although a different version is loaded

I was working on a project to Self host a Web API project.
There are two packages 1) Microsoft.AspNet.WebAPi.SelfHost
2) Microsoft.AspNet.WebApi. I had run into a problem where two different versions of NewtonSoft.Json had been installed by the above packages and it showed a compile-time warning as well as a run time exception. If I install Microsoft.AspNet.WebAPi.SelfHost before Microsoft.AspNet.WebApi then Newtonsoft.Json version 6.0.0.0. is installed by the former and the version 11.0.0.0 by the later which gives the error. but if I install Microsoft.AspNet.WebApi, then version 11.0.0.0 is installed and Microsoft.AspNet.WebAPi.SelfHost doesn't install Newtonsoft.Json but I still get the following error
"Could not load file or assembly 'Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its >dependencies. The located assembly's manifest definition >does not match the assembly reference. (Exception from >HRESULT: 0x80131040)/nSystem.IO.FileLoadException"
although the following is the entry in my web.config reference
"culture="neutral" publicKeyToken="30ad4fe6b2a6aeed"
bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />"
I am really not getting why it is referring to version 6.0.0.0 when a newer version is installed. And if I need both the versions how do I refer to each without causing compiler issues.
Edit: Another thing to mention here is that it errors only after publishing the file but if I run it in release mode, no issue is occurring.
I have tried this after creating a new folder from scratch.
Edit: I have also tried checking the GAC. Newtonsoft.JSON is not available in the GAC. Can anyone tell how to check the manifest/config file of a third-party package like the Microsoft.AspNet.WebAPi.SelfHost
Edit: I also checked the solutions from the linked thread, but it didn't help.
Edit: I just now edited Microsoft.Owin from version 2.0.2 to version 4, but strangely after publishing and running it is still referring to version 2. I checked web.config and package.config, they have correct assembly redirects as well as correct package. So i guess there is some other place where it is not getting updated. Anyone can help me on this?

Missing project dependency when referring project

I'm facing some issues with dependencies when referring projects in Visual Studio. Here is how my solution ReferenceTest is structured:
Common. A class library containing a static CommonClass.HelloWorld() method returning a string. The string returned by this method is read from a JSON config file using Microsoft.Extensions.Configuration (and a large set of its dependencies) installed using NuGet.
ConsoleApplication1. A console application writing the CommonClass.HelloWorld() string to the console using a static Worker.DoWork() method. This console application has a project reference to the Common project.
ConsoleApplication1Test. A class library using NUnit for testing that the Worker.DoWork() method from the ConsoleApplication1 is returning the expected string. This class library has a project reference to the ConsoleApplication1 project.
The ConsoleApplication1 console application is working as expected, but when running the unit test in ConsoleApplication1Test I get this exception:
System.IO.FileNotFoundException : Could not load file or assembly
'System.Runtime, Version=4.1.1.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The
system cannot find the file specified.
The System.Runtime.dll file (and perhaps others) is not copied to the bin-folder when compiling the ConsoleApplication1Test project. Why is this happening?
A zip-file with the demo solution can be found here:
http://www.filedropper.com/referencetest
Solution
I was able to reproduce and resolve this issue, and generate build logs that illustrate the differences.
First, the solution. I noticed that the ConsoleApplication1.csproj file had a line of configuration that the Test project did not. So, I added:
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
to the Test project file. The first <PropertyGroup> section now looks like this:
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A97E82A2-2EF9-43AB-A46B-882131BAF1D0}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ConsoleApplication1Test</RootNamespace>
<AssemblyName>ConsoleApplication1Test</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
The unit test now fails because it can't find config.json. Success!
Edit: after running the build from the command line per below, the unit test passed. I'm not sure why config.json wasn't present when building from Visual Studio.
Partial Explanation
This AutoGenerateBindingRedirects property seems to change the way that the build process resolves references to libraries that are part of the .NET Framework. For example, a before and after verbose log output comparison shows that:
Unified Dependency "System.Runtime, Version=4.0.20.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". (TaskId:97)
Using this version instead of original version "4.0.0.0" in "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\Microsoft.Extensions.Configuration.Abstractions.dll" because there is a more recent version of this framework file. (TaskId:97)
Using this version instead of original version "4.0.0.0" in "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\Microsoft.Extensions.Configuration.dll" because there is a more recent version of this framework file. (TaskId:97)
Using this version instead of original version "4.0.0.0" in "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\Microsoft.Extensions.Configuration.Binder.dll" because there is a more recent version of this framework file. (TaskId:97)
Using this version instead of original version "4.0.0.0" in "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\Microsoft.Extensions.Primitives.dll" because there is a more recent version of this framework file. (TaskId:97)
Using this version instead of original version "4.0.0.0" in "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\Microsoft.Extensions.FileProviders.Abstractions.dll" because there is a more recent version of this framework file. (TaskId:97)
Using this version instead of original version "4.0.0.0" in "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\System.Runtime.CompilerServices.Unsafe.dll" because there is a more recent version of this framework file. (TaskId:97)
Resolved file path is "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7\Facades\System.Runtime.dll". (TaskId:97)
Reference found at search path location "{TargetFrameworkDirectory}". (TaskId:97)
Changes to:
Unified Dependency "System.Runtime, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". (TaskId:97)
Using this version instead of original version "4.0.0.0" in "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\Microsoft.Extensions.Configuration.Abstractions.dll" because AutoUnify is 'true'. (TaskId:97)
Using this version instead of original version "4.0.0.0" in "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\Microsoft.Extensions.Configuration.dll" because AutoUnify is 'true'. (TaskId:97)
Using this version instead of original version "4.0.0.0" in "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\Microsoft.Extensions.Configuration.Binder.dll" because AutoUnify is 'true'. (TaskId:97)
Using this version instead of original version "4.0.0.0" in "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\Microsoft.Extensions.Primitives.dll" because AutoUnify is 'true'. (TaskId:97)
Using this version instead of original version "4.0.0.0" in "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\Microsoft.Extensions.FileProviders.Abstractions.dll" because AutoUnify is 'true'. (TaskId:97)
Using this version instead of original version "4.0.0.0" in "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\System.Runtime.CompilerServices.Unsafe.dll" because AutoUnify is 'true'. (TaskId:97)
Resolved file path is "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug\System.Runtime.dll". (TaskId:97)
Reference found at search path location "C:\Users\User\Desktop\ReferenceTest\ConsoleApplication1\bin\Debug". (TaskId:97)
I'd imagine that the assembly binding redirects in the app.config file are influencing some aspect of the assembly reference path resolution during the build process. This is supported by the appearance of this build output, only after adding the specified property:
Added Item(s):
_ResolveAssemblyReferencesApplicationConfigFileForExes=
app.config
OriginalItemSpec=app.config
TargetPath=ConsoleApplication1Test.dll.config
I have not seen this particular property before and I don't know why it would be included in some projects but not others, or if there is a UI to alter this setting.
For reference, to produce the build output comparisons above, I did the following:
Load the project from the link provided in the question
Add the NUnit3TestAdapter NuGet package to the Test project (personal preference - the error was present when using the VS test runner)
Run the tests to verify the errors
Clean the solution
Run msbuild /verbosity:diag ReferenceTest.sln > build.txt from the Developer Command Prompt in the solution folder
Modify the Test project as described above
Run msbuild /verbosity:diag ReferenceTest.sln > build2.txt
Run devenv /diff build.txt build2.txt or your favorite compare tool
It seems that Newtonsoft.Json library which you are referencing from Common is referencing by itselft to System.Runtime ver 4.0
But all your project are targeted to 4+ framework.
That`s the point of conflict.
Try upgrade or reinstall NuGet package with Newtonsoft.Json library or downgrade the targeted framework of all project to ver 4.0.

Categories