Prevent duplicating files in NuGet content and contentFiles folders

Found updated documentation describing this in detail at MSBuild targets for NuGet.

By default, everything gets added to the root of the content and contentFiles\any\<target_framework> folder within a package and preserves the relative folder structure, unless you specify a package path:

<Content Include="..\win7-x64\libuv.txt">
  <Pack>true</Pack>
  <PackagePath>content\myfiles\</PackagePath>
</Content>

If you want to copy all your content to only a specific root folder(s) (instead of content and contentFiles both), you can use the MSBuild property ContentTargetFolders, which defaults to "content;contentFiles" but can be set to any other folder names. Note that just specifying "contentFiles" in ContentTargetFolders puts files under contentFiles\any\<target_framework> or contentFiles\<language>\<target_framework> based on buildAction.


If you only want to output the file to the build output (content only copies the file to the output directory but does cause it to be set as copy to output directory item), you can use a completely different approach by creating an msbuild file that will be included in the project.

You can do this by putting both the file - say test.jpg into the tools folder (you could also use build) and add a Your.Package.Id.targets file to the build folder (the name being the package id of your package with .targets as extension) with the following content:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Content Include="$(MSBuildThisFileDirectory)..\tools\test.jpg">
      <Link>test.jpg</Link>
      <Visible>false</Visible>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </Content>
  </ItemGroup>
</Project>

This target will be automatically imported into the project files regardless of which "style" of NuGet reference is used (packages.config, PackageReference) and should be backwards compatible to older versions of VS as long as they support NuGet and ToolsVersion 4.0.

The Link metadata denotes where in the output / publish directories the file will end up. You could set it to e.g. defaultContent\images\foo.jpg to create a nested structure and rename the file. (you could even use MSBulid variables to use some of the referencing project's configuration). The Visible metadata prevents the solution explorer from showing the full relative path to the file, which could end up in lots of nested .. nodes. The CopyToPublishDirectory applies to .NET Core / ASP.NET Core apps or SDK-based projects using the Publish target for publishing.

Note that you can set the Inclue-path to anything depending on where in your package the file is. You can also use wildcards (but then set Link to %(Filename)%(Extension))