I recently moved to Visual Studio 2017 Community Edition. It has 2 nice new features:
You don't need to explicitly include your source files in the csproj. It does this automatically.
It can build NuGet packages directly.
I want to package up my open source CodeFirstWebFramework
DLL as a NuGet package. As well as including the DLL
, the package has to include a whole directory tree of other files (including .js, .tmpl, .css and .md files).
How do I tell Visual Studio that I want this directory tree included in the package?
From what information I have found with extensive searching, and ignoring all the out-of-date information that involves adding files to the csproj, all I could find was to place them in a contentFiles
folder, but this does not seem to work.
My project file looks like this:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net45</TargetFramework> <GeneratePackageOnBuild>True</GeneratePackageOnBuild> <Authors>Nikki Locke</Authors> <Company>Trumphurst Ltd</Company> <Description>Easy to use web server for building web apps that use sql databases generated from c# classes</Description> <Copyright>2017 Trumphurst Ltd.</Copyright> <PackageProjectUrl>https://github.com/nikkilocke/CodeFirstWebFramework</PackageProjectUrl> <RepositoryUrl>https://github.com/nikkilocke/CodeFirstWebFramework</RepositoryUrl> <RepositoryType>Github</RepositoryType> <PackageTags>C# SQL Code First Web Server</PackageTags> </PropertyGroup> <ItemGroup> <PackageReference Include="Markdig" Version="0.12.1" /> <PackageReference Include="Mono.Data.Sqlite.Portable" Version="1.0.3.5" /> <PackageReference Include="mustache-sharp" Version="0.2.10" /> <PackageReference Include="MySql.Data" Version="6.9.9" /> <PackageReference Include="Newtonsoft.Json" Version="10.0.2" /> </ItemGroup> <ItemGroup> <Reference Include="System.Net" /> <Reference Include="System.Web" /> </ItemGroup> </Project>
Wildly guessing what I might need to do from the conflicting and out-of-date information on the web, I have added the following:
<ItemGroup> <Content Include="contentFiles/**/*.*" copyToOutput="true"> <IncludeInPackage>true</IncludeInPackage> </Content> </ItemGroup>
Now the .nupkg
file has the contents of the contentFiles
folder inside it (in two places, a content
folder, and a contentFiles
folder).
However, when I install the package in another project, the content files do not appear, although they are listed in the project.assets.json
file in the obj
folder.
You first have to tell Visual Studio about the location of your package, and then you can add it to a project. What most people do is go into the NuGet Package Manager and add the local folder as a source (menu Tools → Options → NuGet Package Manager → Package Sources).
You can configure Visual Studio to automatically generate the NuGet package when you build the project. In Solution Explorer, right-click the project and choose Properties. In the Package tab, select Generate NuGet package on build.
I have now changed my project file again, so it now reads:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net45</TargetFramework> <GeneratePackageOnBuild>True</GeneratePackageOnBuild> <Authors>Nikki Locke</Authors> <Company>Trumphurst Ltd</Company> <Description>Easy to use web server for building web apps that use sql databases generated from c# classes</Description> <Copyright>2017 Trumphurst Ltd.</Copyright> <PackageProjectUrl>https://github.com/nikkilocke/CodeFirstWebFramework</PackageProjectUrl> <RepositoryUrl>https://github.com/nikkilocke/CodeFirstWebFramework</RepositoryUrl> <RepositoryType>Github</RepositoryType> <PackageTags>C# SQL Code First Web Server</PackageTags> </PropertyGroup> <ItemGroup> <PackageReference Include="Markdig" Version="0.12.1" /> <PackageReference Include="Mono.Data.Sqlite.Portable" Version="1.0.3.5" /> <PackageReference Include="mustache-sharp" Version="0.2.10" /> <PackageReference Include="MySql.Data" Version="6.9.9" /> <PackageReference Include="Newtonsoft.Json" Version="10.0.2" /> </ItemGroup> <ItemGroup> <Reference Include="System.Net" /> <Reference Include="System.Web" /> </ItemGroup> <ItemGroup> <Content Include="contentFiles/**/*.*" copyToOutput="true"> <IncludeInPackage>true</IncludeInPackage> <CopyToOutput>true</CopyToOutput> <BuildAction>Content</BuildAction> <copyToOutput>true</copyToOutput> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> </ItemGroup> <ItemGroup> <Compile Remove="Phone\**" /> <EmbeddedResource Remove="Phone\**" /> <None Remove="Phone\**" /> </ItemGroup> </Project>
The contentFiles are now successfully copied into a folder of the same name (i.e. contentFiles
) in any project that downloads the NuGet package - not sure which directive worked, but one of them did.
The content is not automatically copied to the project's output folder on compile, unfortunately - suggestions welcome.
First, please be aware that you need to put your files either into a content or contentFiles folder depending on how you NuGet package is referenced. See the end of this section.
Basically, if a NuGet project is referenced by package.config file, the files from the content folder of the NuGet package will be copied to the referencing project. If the NuGet package is referenced by PackageReference in the project file, the files from the contentFiles folder within the package will be used. It is recommended to include both.
The structure of the contentFiles folder can be found here. It is possible to specify the language and the framework for the files to be copied.
So in your case:
<ItemGroup> <Content Include="contentFiles/**/*.*"> <Pack>true</Pack> <PackagePath>contentFiles\any\any;content</PackagePath> </Content> </ItemGroup>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With