Search code examples
.netvisual-studio.net-corenugetnuget-package

Why are content files from NuGet packages added as links in .NET Core projects and how can you prevent that?


I am developing a .NET Standard library and plan to use it in both .NET Core and .NET Framework projects. My library is dependant on a third library which itself is dependant on a few C binary files. The C binary files have to be copied to the output directory of the project which will be referencing my library.

I added the binary files to my library project as content and they are copied to the content and contentFiles directories when the NuGet package is packed with the dotnet pack command. The files are also listed in the nuspec file.


However when I install the NuGet package there are two different behaviours to observe depending if I install it to a .NET Framework or .NET Core project:

.NET Framework

The binary files I added to my library project are also added to the referencing project and I can copy them to the output directory. This is the behaviour that I expect, want and works.

.NET Core

The binary files I added to my library project are also added to the referencing project but as links which also works but only on my machine of course since the NuGet packages are stored in the Windows user folder by default. This create problems for anyone else that will work on the same project on a different machine as the links to the files are broken in that case.


I already tried messing around with the nuspec file itself but this doesn't really help since I only get the nuspec file after packing which is done by CI pipeline.

Why is the behaviour for .NET Framework and .NET Core project different in that case and is it possible to get the behaviour of a .NET Framework project in a .NET Core project?


Solution

  • Actually, this is the normal behavior.

    And what you saw of content and contentFiles's behavior is normal and the rule of them is designed by Microsoft.

    Please refer to this similar issue and this one.

    Content node will pack its content as the real files into the main project. This is for Net Framework projects with packages.config nuget management format.

    While, ContentFiles node will pack its content as link format into the main project(Net Core and Net Standard projects). This is for PackageReference nuget management format.

    So if you want this feature is the same as the Net Framework project on Net Core, you should use a <package_id>.props on net standard projects to get what you want.

    Steps

    1) create a file called <packages_id>.props file under the build folder on your net standard lib project.

    enter image description here

    Note: if your lib nuget is called lib.1.0.0.nupkg, the props file should be named as lib.props file so that it will work. It should be the same as the nuget_id.

    2) add these on lib.props file:

    <Project>
      <Target Name="CopyFiles" BeforeTargets="Build">
        <ItemGroup>     
          <File Include="$(MSBuildThisFileDirectory)..\Binary\*.*"></File>          
        </ItemGroup>
          <Copy SourceFiles="@(File)" DestinationFolder="$(ProjectDir)Binary"></Copy>
      </Target>
    </Project>
    

    3) add these on xxx.csproj file of the lib project.

    <ItemGroup>
    <None Include="xxx\**.**"(all the binary files) Pack="true" PackagePath="Binary"></None>
    <None Include="build\lib.props" Pack="true" PackagePath="build"></None>
    </ItemGroup>
    

    4) It will copy the binary files into a folder called Binary into your main project when you install this new version of the nuget package.

    Also, when you install this new version of nuget package, please clean your nuget caches or delete all files under C:\Users\xxx(current user)\.nuget\packages.

    Besides, there is a similar issue about the steps.