Erroneous dependency resolving for multi-targeting NuGet package - c#

I am being confused by how dependencies are resolved when using a group-based dependency specification in NuGet.
I have a Visual Studio project targeting .NET Framework 4.6.1, with a NuGet dependency to a NuGet package (internal to my company):
This is in the packages.config file of my project:
<package id="Name.Of.My.Package" version="2.0.65" targetFramework="net461" />
And this is in the .csproj file:
<Reference Include="Name.Of.My.Package, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Name.Of.My.Package.2.0.65\lib\net45\Name.Of.My.Package.dll</HintPath>
</Reference>
That package is a multi-targeting package with a group-based dependency specification, which looks like this when I get it straight from the .nuspec file obtained by opening the packages\Name.Of.My.Package.nupkg file as an archive:
<dependencies>
<group>
<dependency id="Newtonsoft.Json" version="11.0.2" />
</group>
<group targetFramework=".NETFramework4.0">
<dependency id="Microsoft.Bcl.Async" version="1.0.168" />
</group>
</dependencies>
And the packages\Name.Of.My.Package\lib folder contains:
net40
net45
nestandard2.0
So my understanding here is that because my project is in net461, the reference should be added to the net45 version of my package (as seems to be the case if I look at the .csproj file), but more importantly that the only implicit dependency should be to Newtonsoft.
But this happens when I try to remove the Microsoft.Bcl.Async package in the package manager console:
Uninstall-Package Microsoft.Bcl.Async
Attempting to gather dependency information for package 'Microsoft.Bcl.Async.1.0.168' with respect to project 'Name.Of.My.Project', targeting '.NETFramework,Version=v4.6.1'
Resolving actions to uninstall package 'Microsoft.Bcl.Async.1.0.168'
Uninstall-Package : Unable to uninstall 'Microsoft.Bcl.Async.1.0.168' because 'Name.Of.My.Package.2.0.65' depends on it.
This is happening in the latest version of Visual Studio 2017 (15.8.6).

Erroneous dependency resolving for multi-targeting NuGet package
This is the correct behavior of nuget. As we know, .NET Frameworks are backwards compatible. Meaning if your project is targeting v4.6, you can consume packages with lower versions, such as v4.5, v4.0.
NuGet's specialty is compatibility checking (if packages are authored
correctly ofc) :) NuGet knows the available frameworks are v3.5, v4.0,
v4.6 and netstandard1.3. The "nearest" compatible framework with v4.5
is v4.0, so it'll pick the v4.0 assets when you install it.
Source: How to figure out the information of dependency packages for missing frameworks
So nuget will install the dependence "nearest" backwards compatible framework v4.6.1, in you case, the dependency Microsoft.Bcl.Async will also be installed.
That is the reason why you could not uninstall the package Microsoft.Bcl.Async when you have package Name.Of.My.Package installed.
For example, when you add the package Microsoft.AspNet.WebApi.Client 5.2.6 to the .net framework 4.6.1 project, nuget will also add the dependency Newtonsoft.Json (>= 6.0.4) under the .net framework 4.5:
Check this document for some more details.

Related

Azure custom Nuget package external libraries

I created a project that is automatically packed into a NuGet package and added to Azure Artifacts through a pipeline
My NuGet package uses a library from nuget.org called "TextFieldParserStandard"
I install my NuGet by adding the Artifacts Feed package source in Visual Studio
I import classes and use functions, but I receive the error:
System.IO.FileNotFoundException
HResult=0x80070002
Message=Could not load file or assembly 'TextFieldParserStandard, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
If I manually search and add this library in my projects where I use the NuGet, my NuGet works. But they should come automatically. When I install other packages I don't need to manually install their libraries.
So the problem is "TextFieldParserStandard" is not installed automatically at once with my NuGet installation.
In Artifacts Feed, I have only my package "MyNuGet version 1.0.0.11538". I don't know if I should have "TextFieldParserStandard" in my Feed.
In Visual Studio, Manage NuGetPackages, my NuGet does not have any dependencies.
My NuGet SDK: .NET Standard 2.0 (note: compatible with imported projects since it works if I manually add TextFieldParserStandard).
If needed I can give the yaml pipeline. This targets somehow the problem. Build NuGet Package automatically including referenced dependencies
But adding IncludeReferencedProjects to yaml did not solve.
Azure custom Nuget package external libraries
That because you are not add the reference package TextFieldParserStandard to your custom package MyNuGet as dependency.
In this case, it will not automatically install the reference package TextFieldParserStandard to your project when you install the package MyNuGet.
To resolve this issue, you could add the property <PrivateAssets>all</PrivateAssets> for the package TextFieldParserStandard in your project MyNuGet file MyNuGet.csproj:
<ItemGroup>
<PackageReference Include="TextFieldParserStandard" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
Submit this change to the repo, then generate the new package for your custom package, it will have the TextFieldParserStandard package as dependecy:
Update:
Since TextFieldParser cannot be referenced in unit tests.
You could try to create your .nupsec file with Dependencies element, like:
<dependencies>
<dependency id="another-package" version="3.0.0" />
<dependency id="yet-another-package" version="1.0.0" />
</dependencies>
You can refer this document for some more details.

Nuget package creation - Class library that targets .NET framework 4.6.1 can not target correct framework

I created a class library that targets .net framework 4.6.1 (so pretty much a blank canvas, with a single method to return a string, just for testing purposes). I want to make this into a nuget package. I'm following this article https://learn.microsoft.com/en-us/nuget/quickstart/create-and-publish-a-package-using-visual-studio-net-framework , but when I get to "nuget pack" I get the following warning:
"WARNING: NU5128: Some target frameworks declared in the dependencies group of the nuspec and the lib/ref folder do not have exact matches in the other location. Consult the list of actions below:
- Add a dependency group for .NETFramework4.6.1 to the nuspec"
I tried adding the dependency group to the .nuspec file:
<?xml version="1.0"?>
<package>
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>Author</authors>
<owners>$author$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>H</description>
<copyright>Copyright 2019</copyright>
<tags>blah</tags>
<dependencies>
<group targetFramework=".NETFramework4.6.1" />
</dependencies>
</metadata>
</package>
and I also tried:
<?xml version="1.0"?>
<package>
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>Author</authors>
<owners>$author$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>H</description>
<copyright>Copyright 2019</copyright>
<tags>blah</tags>
<dependencies>
<group targetFramework="net461" />
</dependencies>
</metadata>
</package>
I still get same error.
I tried using older versions of nuget, where the warning message isn't shown, but the same problem persists (If I try to add via the package manager, it says it has no dependencies).
WARNING: NU5128: Some target frameworks declared in the dependencies
group of the nuspec and the lib/ref folder do not have exact matches
in the other location. Consult the list of actions below.
This is an open issue in Github/Nuget, see #8713. I can reproduce same issue in my VS2017 with Nuget V5.3, and this issue goes away if I use Nuget V5.2 or earlier. For this situation, I'm afraid you have to use earlier versions of Nuget.exe until the team releases the fix.
If I try to add via the package manager, it says it has no
dependencies
1.If it displays no package dependencies though your package project depends on some nuget packages, please check if you're using packageReference to manage nuget in your current project. For now, nuget pack command doesn't work well for .net framework projects with packageReference or new SDK format projects.
You can check details from Leo's answer to resolve this issue.
2.If the no dependencies you mean is that when one project consumes your package, it doesn't display which framework your project targets like this:
(We can see your package depends on Newtonsoft.Json but we can't find which framework it targets(net461).)
For this, we need to use command like nuget pack xx.nuspec to add the dependencies+group into package when packing. Then we can see both targets framework and dependent packages like this:
Hope all above helps and if I misunderstand anything, feel free to correct me :)

Reference .NET 4.5 dll in .NET Core 1.1 csproj?

I'm running VS 2017 RC4.
I add a reference in my .NET Core app to my .NET 4.5 dll and it compiles. When a line that references the dll is called at runtime, I get:
System.IO.FileNotFoundException: 'Could not load file or assembly 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. The system cannot find the file specified.'
This image shows that to use 4.5 references, I need to use netstandard 1.1.
https://msdnshared.blob.core.windows.net/media/2016/07/172.png
Assuming that is what I need, how do I reference it in my .csproj? I can only find old documentation for when project.json was used instead.
I tried adding the below but it did not help:
<NetStandardImplicitPackageVersion>1.1</NetStandardImplicitPackageVersion>
Also, I need to add:
<RuntimeFrameworkVersion>1.0.3</RuntimeFrameworkVersion>
Or I get FileNotFoundException: Could not load file or assembly. The system cannot find the file specified.
Why is that?
Here are the relevant parts of my .csproj:
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wp8+wpa81;</PackageTargetFallback>
<RuntimeFrameworkVersion>1.0.3</RuntimeFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="My4.5dll">
<HintPath>Dlls\My4.5dll.dll</HintPath>
</Reference>
</ItemGroup>
You can't (safely) load a .NET Framework 4.5 library into .NET Core, because it may use APIs which are unavailable in .NET Core.
Only if your library targets portable-net45+win8 (.NET Framework 4.5 and Windows 8 Portable Class Profile or higher) it can be used with .NET Core. Because this specific PCL Profile limits the API which is compatible to (what was formerly called WinRT) System.Runtime, which is what is .NET Core is based on.
For a list of compatible PCL profiles, see this list (PCL Compatibility at the bottom)
If the assembly you want to reference do not support netstandard1.x or any of the supported profiles, you have to target .NET Framework 4.5 instead of .NET Core.
In your csproj
<TargetFramework>net45</TargetFramework>
...
<ItemGroup>
<PackageReference Include="Net45DependencyHere" Version="4.5.0" />
or if you multi-target
<TargetFrameworks>net45;netcoreapp1.1</TargetFrameworks>
...
<ItemGroup>
<PackageReference Condition="'$(TargetFramework)' == 'net45' Include="Net45DependencyHere" Version="4.5.0" />
<PackageReference Condition="'$(TargetFramework)' == 'netcoreapp1.1' Include="NetCoreReplacementLibrary" Version="1.1.0" />
You just can't auto-magically use any .NET Framework 4.5 library in your .NET Core project. Only PCL and netstandard1.x ones.
Update
For the sake of completeness:
If you are certain that your class library/package targets a compatible PCL, you can make nuget restore this packages too, even if they don't target netstandard1.x.
<PropertyGroup>
<PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wp8+wpa81;</PackageTargetFallback>
</PropertyGroup>
Word of warning
Never, I repeat, NEVER put anything else there except for compatible PCL Libraries. NEVER put net45 in here. This will just force NuGet to download and install this package, but it won't make it work and crash at runtime with similar error like you have above!
It's only there to force nuget to install package which are know to work with .NET Core for the transition period until most packages target netstandard1.x!
I had the same problem, but with .NET Standard 2.0 and a .NET Framework 4.0 assembly. The solution was create a nuget with my dll in nuget package explorer targeting .NET Standard 2.0, then add the package to the project.
Link to nuget explorer: https://github.com/NuGetPackageExplorer/NuGetPackageExplorer

Nuget seems to install the wrong version of System.Collections.Immutable

I have a confusing issue with Nuget. I have a number of projects who claim to have System.Collections.Immutable installed at version 1.3.0 but if I look at the version of the dll in all the references I see version 1.2.1.0
When I open up the DLL with JustDecompile I see
which declares that the DLL version is indeed 1.2.1.0 but has been installed in directory packages\System.Collections.Immutable.1.3.0
A typical packages.config file will contain
<package id="System.Collections.Immutable" version="1.3.0" targetFramework="net452" />
and the csproj is
<Reference
Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)packages\System.Collections.Immutable.1.3.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
If I try to open the downloaded nuget package from the gallery and open with nuget package explorer I get
The NuGet package version and the assembly version are not necessarily the same. There is no restriction on what versions are used in either.
So looking at System.Collections.Immutable 1.3.0 the assembly version is 1.2.1.0 for the assemblies in the NuGet package.
If you cannot open the NuGet package in the NuGet Package Explorer you can open it in a zip file application such as 7-zip. Or just rename the file to .zip and open it with the built-in Windows zip file extractor.
Got the same problem recently. System.Collections.Immutable is a multi-target package, so the version of the assembly imported to your solution depends on the target. For instance, if you are in a .Net Framework project, this is the file stored in portable-net45+win8+wp8+wpa81 that will be used, hence the different version.

How is the necessary version of a nuget package defined?

I am trying to determine how a version number is determined for a nuget package.
I assumed that this would be in the packages.config file. In the packages.config file, this is the version number it is looking for: <package id="UnitClassLibrary" version="1.1.0" targetFramework="portable-net40+sl40+win+wp" /> Likewise, in the .csproj file, it is looking for <Reference Include="UnitClassLibrary, Version=1.1.0, Culture=neutral, processorArchitecture=MSIL">.
So I have defined a need for version 1.1.0 in both of these files. However, when I try to run a nuget restore command, it reports Unable to find version '1.10' of package 'UnitClassLibrary'. I cannot find anywhere that the nuget version is defined as 1.10.

Categories