19

I got an issue with a custom Nuget package I've created. Let's call it MyCompany.Library.nupkg. It is hosted on an corporate Artifactory Nuget repo. This package depends on Newtonsoft.Json. For some reason the dependent DLL is not copied to the output folder of my project, if I reference a project that uses that Nuget package. The weird thing is, that when I use another package (e.g. Moq, instead of my own) the dependent DLLs are copied.

I've created test solution to reproduce the issue:

Solution ReferenceTest:

  • Project: SomeLib.dll; references:
    • MyCompany.Library Nupkg (depends on Newtonsoft.Json, so that's added too)
    • Moq Nupkg (depends on Castle.Core, added too)
  • Project: MyWinFormsApp.exe; project-reference:
    • SomeLib.csproj

When I look at the output folder of SomeLib, I see:

  • SomeLib.dll
  • Moq.dll
  • Castle.Core.dll
  • MyCompany.Library.dll
  • Newtonsoft.Json.dll

That looks good.

But when I look at the output folder of MyWinFormsApp, Newtonsoft.Json.dll is missing and when running the application, it throws exceptions that the Newtonsoft.Json dll is not found. However, the Castle.Core.dll IS in the output folder of MyWinFormsApp.

I've compared the nuspecs of Moq and MyCompany.Library and I can't really find any significant difference.

I could change all of the project that use my SomeLib to reference Newtonsoft.Json, but that's a lot of projects and I don't want to bother the other developers with that. They shouldn't have to know that SomeLib uses that assembly.

The references in the SomeLib.csproj are like this:

  <ItemGroup>
    <Reference Include="MyCompany.Library, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\packages\MyCompany.Library.1.0.0\lib\net461\MyCompany.Library.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Castle.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
      <HintPath>..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Moq, Version=4.5.28.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
      <HintPath>..\packages\Moq.4.5.28\lib\net45\Moq.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <HintPath>..\packages\Newtonsoft.Json.8.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Xml" />
  </ItemGroup>

My Nuspec looks like this:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
  <metadata>
    <id>MyCompany.Library</id>
    <version>0.0.0</version>
    <description>MyCompany Core library</description>
    <authors>MyCompany</authors>
    <references>
      <reference file="MyCompany.Library.dll" />
    </references>
    <dependencies>
      <dependency id="Newtonsoft.Json" version="[8.0,9.0.1]" />
    </dependencies>    
  </metadata>
  <files>
    <file src="MyCompany.Library\bin\Release\MyCompany.Library.dll" target="lib\net461"/>
    <file src="MyCompany.Library\bin\Release\MyCompany.Library.pdb" target="lib\net461"/>
    <file src="MyCompany.Library\bin\Release\MyCompany.Library.xml" target="lib\net461"/>
  </files>
</package>

I'm using Visual Studio 2015 Professional.

My questions:

  1. Why is Visual Studio not copying my dependent dll?
  2. Why is it copying the dependencies of Moq? What's the difference?

Thanks for any help.

Quido

EDIT

I've been comparing the NUSPEC of Moq and my own package and (completely desperate) I found one diffence. The Moq Nuspec contains:

<dependencies>
  <group targetFramework=".NETFramework4.5">
    <dependency id="Castle.Core" version="3.3.3" />
  </group>
</dependencies>

and my own package contains:

<dependencies> 
  <dependency id="Newtonsoft.Json" version="[8.0,9.0.1]" /> 
</dependencies>     

I changed my dependency to specify a targetFramework and now VisualStudio DOES copy my dependency!

That NuSpec is the only thing I changed and this really solves it. I've been going back and forth to a situation with and without that targetFramework and the results are consistent (failure without the targetFramework and success with the targetFramework).

So: problem solved, but I have no idea why...

Quido
  • 432
  • 1
  • 4
  • 12
  • I've found another question on this topic. http://stackoverflow.com/questions/1132243/msbuild-doesnt-copy-references-dll-files-if-using-project-dependencies-in-sol It looks like a bug in VS / MSBuild. The accepted answer on that topic explains it pretty well. – Quido Apr 09 '17 at 21:17

2 Answers2

1

1.Why is Visual Studio not copying my dependent dll?

Just as you comment, MSBuild doesn't copy references (DLL files) if using project dependencies in solution in order to avoid reference pollution in project SomeLib project. So the references of referenced project will not copy to the output folder.

2.Why is it copying the dependencies of Moq? What's the difference?

As the answer in the first question, the dependencies of Moq should not copy to the output folder of MyWinFormsApp. So you need to check if you have installed the Moq package to the MyWinFormsApp project and you can check the References of MyWinFormsApp, make sure you just only have a project reference of SomeLib project.

Hope this can help you.

Leo Liu-MSFT
  • 52,692
  • 7
  • 69
  • 81
  • 4
    Thanks for your response. What you call "reference pollution", is "satisfying dependencies" in my opinion. That solution simply requires that assembly. It just won't start without it. And I am very sure I haven't added a reference to Moq in MyWinFormsApp. See my edit in the origin post for some more insights... – Quido Apr 11 '17 at 10:00
  • Not sure how did you created test solution. Have you ever pack the SomeLib project, then install it to MyWinFormsApp project? Or just project reference? My reproduce steps is: create SomeLib project->add Moq nuget package->create console Application project MyWinFormsApp->Add SomeLib project as project reference to MyWinFormsApp project(not pack SomeLib project)->Build MyWinFormsApp project. Any different with you? – Leo Liu-MSFT Apr 12 '17 at 09:12
-1

Right click on "Newtonsoft.json" reference in project and select properties. In property page check if "Copy Local" property is set to "True".

Pankaj Kapare
  • 6,540
  • 3
  • 33
  • 52
  • 3
    In SomeLib.csproj, the Copy Local is set to true. That's why it's copied to the output folder of that project. The MyWinFormsApp project does not have a reference to that DLL, so I can't set the Copy Local. – Quido Apr 06 '17 at 19:06