Is there a way to control Nuget's over-eager references? - nuget

I'm just getting started with Nuget, and moving much of my team's intra-team and interdepartmental references into packages on a private nuget feed. The thing I'm observing though is that when my packages have their own dependencies, those secondary dependencies get added to my projects as references as though the projects are using them directly.
This works from a build & release perspective since the dependencies get packaged up correctly, but for larger projects the references list gets rather bloated compared to the assemblies actually referenced in code. In a hypothetical cleanup exercise, it seems like it would be difficult to determine which assemblies were this type of secondary dependency and which were simply no longer used.
Is this just an unfortunate consequence of Nuget works? Is there a different way to use Nuget that doesn't result in these noisy references?
For example: I have project MyProject, which uses assembly DependencyA directly. DependencyA references assembly LibraryX and as such LibraryX is required at runtime for MyProject, even though MyProject doesn't use it directly. For the sake of the example let's say LibraryX is distinct enough for it to be its own package.
In this scenario, prior to Nuget, the assemblies would live in source control, and could be packaged up during build/publish/deploy without needing an assembly reference in MSBuild. In this case MyProject has an MSBuild assembly reference to DependencyA, but not to LibraryX.
However, upon migrating to Nuget and consuming these dependencies via packages, the nuspec for DependencyA expresses a dependeny on LibraryX:
<package >
<metadata>
<id>DependencyA</id>
<version>1.0.0</version>
<authors>Initech</authors>
<owners>Initech</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<description>A Dependency</description>
<tags>Dependency A</tags>
<dependencies>
<group targetFramework="net40" >
<dependency id="LibraryX" version="1.0.0" />
</group>
</dependencies>
</metadata>
</package>
When installing the DependencyA package on MyPrject, Nuget adds an MSBuild assembly reference for LibraryX to MyProject even though MyProject doesn't actually directly reference LibraryX.

You can control which assets are allowed to flow up the dependency chain using PrivateAssets, which I think is what you mean.
By default everything flows up though, so you can use packages you only depend on transitively in your code - in other words, the distinction between compile and runtime dependencies you mentioned in your comment doesn't exist by default.

Related

How to I make a nuget package referenced by the nuget package I'm creating get installed as a top-level packagereference?

I'm creating a nuget package that uses refit as a dependency and when consuming the produced package I need to ensure refit gets installed as a top level package in the consuming project instead of a transitive reference.
I'm using the new csproj file format to create the nuget package and currently referencing refit like this:
<ItemGroup>
...
<PackageReference Include="Refit" Version="4.0.1" />
...
</ItemGroup>
Is there an attribute I can specify to make sure this gets added as a top-level package reference when my nuget package gets consumed?

nuget pack ignores package.config dependencies

I cannot get nuget pack X.csproj to recognize package dependencies in a project. Amazingly, when packaging, the diagnostic message “Found packages.config. Using packages listed as dependencies” is printed, but in the end the <dependencies/> tag in the .nuspec file inside the package is empty.
The packages.config for the project does indeed contain references:
<packages>
<package id="SmartAction.Logger" version="1.0.2.0" targetFramework="net40" />
<package id="SmartAction.Pervasive" version="1.0.1.0" targetFramework="net40" />
</packages>
To narrow the problem down, I removed my own parallel .nuspec file, and mostly all switches from the nuget pack command:
> nuget pack libToneDetection.csproj -prop Configuration=Release
MSBuild auto-detection: using msbuild version '14.0' from 'C:\Program Files (x86)\MSBuild\14.0\bin'.
Attempting to build package from 'libToneDetection.csproj'.
Packing files from '[snip]\Core\ToneDetection\libToneDetection\bin\Release'.
Found packages.config. Using packages listed as dependencies
Successfully created package '[snip]\Core\ToneDetection\libToneDetection\SmartAction.Audio.ToneDetection.1.0.0.0.nupkg'.
NuGet Version: 3.3.0.212
The only difference I can spot with this project is that its name is different from package name (I am trying to maintain them in sync but this is older stuff I am repackaging).
I doubt I had ever seen this before. I am finding questions on SO from people trying to prevent references in packages.config from becoming dependencies of the package, but none from those trying, like me, to beat the reverse problem. Help!
Addendum. I copied the project out of the solution with other projects to a temporary directory and rebuilt the package from there. Now one of the two dependencies from packages.config was added to the package:
<dependencies>
<dependency id="SmartAction.Logger" version="1.0.2.0" />
</dependencies>
Thinking of the differences between the two, the SmartAction.Logger package depends on SmartAction.Pervasive. But the package I am compiling really uses both.
To me, either behavior looks incorrect. Am I hitting a nuget bug, or a cryptic complex feature?
Xref: Opened https://github.com/NuGet/Home/issues/1867

Nuget package dependency being treated as sub depedency looses version constraint

Let's say I create a new class library project. I add the Entity Framework 6.1 NuGet package to it, then create a new NuGet package from the class library project with nuget pack MyProject.csproj. I get a nice npkg with a depedency to Entity Framework 6.1.
Then, I decide to add a reference to the GraphDiff NuGet package which has a dependency to EntityFramework >= 6.0, the resulting class library npkg has only a dependency to GraphDiff and a note that it may have sub-dependencies, but nothing about it being Entity Framework and especially version 6.1.
Problems arise when I include the class library npkg into a project: Entity Framework 6.0 gets installed while it should have installed 6.1.
Is there a way around this?
I get this with NuGet.exe 2.8.50926.602
I found that I must use a nuspec file and manually specify a dependencies section, like so:
<?xml version="1.0" encoding="UTF-8"?>
<package>
<metadata>
**snip!!**
<dependencies>
<dependency id="EntityFramework" version="6.1.2" />
</dependencies>
</metadata>
</package>
I haven't been able to change anything working with the nuget project's packages.config file.
There's some valuable information about version dependency on Rick Strahl's web log

Creating NuGet package with reference to a non-NuGet reference

I am creating a Class Library that builds 2 dlls into a NuGet package. It has a few references to dlls that currently do not have a NuGet package to be referenced from.
How should I make my NuGet package dependent on those dlls that are currently unavailable via NuGet?
If I bundle them up as well, what happens if a project that already has a reference to these dlls, pulls down my NuGet package, what happens to that reference?
Should I just create a NuGet package for each dll reference and make my NuGet package dependent on these?
You can bundle the DLLs into your NuGet package with no ill effects. A project that already has those DLLs in some /libs (or whatever) folder will continue to reference them from there. Assemblies in your NuGet package will reference the bundled DLLs that are pulled into /packages.
In your nuspec file, use the <file> element to include the internal DLLs, as such:
<package>
<metadata>
...
</metadata>
<files>
<file src="PATH_TO_BIN\DependencyOne.dll" target="mylibs" />
<file src="PATH_TO_BIN\DependencyTwo.dll" target="mylibs" />
</files>
</packages>
This will result in the following file structure when the NuGet package is pulled:
PATH_TO_PROJECT/packages/YOUR_NUGET_PACKAGE/mylibs/DependencyOne.dll
PATH_TO_PROJECT/packages/YOUR_NUGET_PACKAGE/mylibs/DependencyTwo.dll
The target attribute can specify any arbitrary path relative to your package root.

class library with multiple nuget packages issue

I have a class library with numerous projects, each referencing each other, written in C#. This is a common library that I share with other projects. I have recently changed the mechanism that the library is shared to be via nuget. So for each project within the library, I have a post build event to create a nuget package eg.
"$(SolutionDir)\NuGet.exe" pack "$(ProjectPath)" -o "$(SolutionDir)\Packages"
This works nicely. It pushes the package to a shared folder in the file structure and the consuming project installs it from there. All projects packages are pushed to this folder.
I have ran in to a problem though. Lets say my library creates package X and Y. X has a reference to Y in the class library. In the consuming application, I need to use X, when I install it, it doesnt install the ddl from Y. I also need to install package Y. How can I set it up when package X is created, it also includes the necessary dlls's from package Y, without having to explicitly install it?
in the nuspec file of package X you can specify package Y as dependency
<dependencies>
<dependency id="Y" version="1.0" />
</dependencies>
More options around dependency can be found here http://docs.nuget.org/docs/reference/nuspec-reference#Specifying_Dependencies
For specifying files you could use
<files>
<file src="bin\Debug*.dll" target="lib" />
<file src="bin\Debug*.pdb" target="lib" />
</files>
More details here http://docs.nuget.org/docs/reference/nuspec-reference#Specifying_Files_to_Include_in_the_Package