Include file in NuGet package to be copied on installed project folder (no output folder) using Visual Studio - visual-studio

Can a file be packed inside a NuGet package, using Visual Studio, in way that it will be copied inside the target project folder?
I added this code in NuGet .csproj
<ItemGroup>
<Content Include="MyFolder/**/*.*" copyToOutput="true">
<Pack>true</Pack>
<PackagePath>contentFiles/any/any/MyFolder;content/any/any/MyFolder</PackagePath>
<IncludeInPackage>true</IncludeInPackage>
<CopyToOutput>true</CopyToOutput>
<BuildAction>Content</BuildAction>
<copyToOutput>true</copyToOutput>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
</Content>
</ItemGroup>
and when I install the package the content of the MyFolder appears as linked and it will be copied only into the output directory. Instead of a link, is there a way to have the copy of the files?
Thanks.

Related

VS 2019 Solution Explorer references files from old Nuget packages

I'm using Visual Studio 2019 for a .NET Core 3.1 MVC application. I have installed several Nuget packages that I also created. Some of the packages contain their own settings files which need to be copied to the output directory in order for the application to work properly. These settings files are put into their own folder and everything is mostly fine. Sample .csproj file of one of these packages:
<PropertyGroup>
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>[redacted</Authors>
<Company>[redacted</Company>
<Description>[redacted]</Description>
<Version>1.0.2.2-alpha</Version>
</PropertyGroup>
<ItemGroup>
<None Remove="settings\mySettings.Development.json" />
<None Remove="settings\mySettings.Production.json" />
<None Remove="settings\mySettings.Staging.json" />
</ItemGroup>
<ItemGroup>
<Content Include="settings\mySettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<Pack>true</Pack>
</Content>
<Content Include="settings\mySettings.Production.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<Pack>true</Pack>
</Content>
<Content Include="settings\mySettings.Staging.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<Pack>true</Pack>
</Content>
</ItemGroup>
What's strange is when I update one of these packages, sometimes Visual Studio doesn't link to the settings file in the updated package. So for example, this is my .csproj file for the web application.
<Content Update="..\..\..\..\..\.nuget\packages\mypackage\1.0.2.2-alpha\contentFiles\any\netstandard2.0\settings\mySettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="..\..\..\..\..\.nuget\packages\mypackage\1.0.2.2-alpha\contentFiles\any\netstandard2.0\settings\mySettings.Production.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="..\..\..\..\..\.nuget\packages\mypackage\1.0.2.2-alpha\contentFiles\any\netstandard2.0\settings\mySettings.Staging.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
This part looks fine, even if I had to manually change the paths from absolute to relative.
But in the Solution Explorer, when I view the properties for these files, it shows the build action as None and the path is to an older package version. If I then change the build action to Copy always, VS will add instructions for copying the older file to the .csproj.
This is potentially a problem in that if another developer takes over this project, they may not notice the version differences and if they change the build action, they could overwrite the correct settings file with the older one.
I don't see any reference to the older version in the .csproj file, so where is that coming from? Note that the older version of the package is not installed anywhere the solution, either. Does anyone know what the deal is?
Thanks.
You have to clean the nuget cache first or just delete all files under C:\Users\Administrator\.nuget\packages.
Not sure that if your old package version is the same as the new one. In other words, you still make a same package version and did not assign a new one for it which makes VS always install that old one from the nuget cache. So you have to clean the nuget cache folder to remove all the old packages.
So my suggestion is that when you install the new release version of the nuget package, you have to clean nuget caches first, also delete bin and obj folder.
Besides, if you want to make the conent files of the nuget package be copied into the main project's output folder. Please use
<PackageCopyToOutput>true</PackageCopyToOutput>
Check this similar issue.

Restore nuget package in different folder

We have some projects (Plugins) which use in several projects, the output of these projects will copy to the specific folder in the target projects (Plugins folder).
We pack project with Visual studio 2019 Pack option and after that, we push npkg files to our local NuGet server for further use.
The problem is when we want to get these packages, Package Manager should put lib files in the Plugins folder, but unfortunately, the package manager extracts these in the root folder (bin).
My question is: How can I config nuspec file to force package manager to extract to the right folder, and can I do it with visual studio or I have to create nuspec file manually.
You should use a <packages_id>.props file to realize it.
create a file called <packages_id>.props under the build folder of your lib project.
You should note that if your nupkg file is called Plugins.1.0.0.nupkg, you should name this file as Plugins.props so that it will work.
add these on Plugins.props file:
<Project>
<Target Name="CopyFiles" BeforeTargets="Build">
<ItemGroup>
<File Include="$(MSBuildThisFileDirectory)..\Plugins\*.*"></File>
</ItemGroup>
<!--It will copy the plugins output files into the Plugins folder of the goal project-->
<Copy SourceFiles="#(File)" DestinationFolder="$(ProjectDir)Plugins"></Copy>
</Target>
</Project>
add these on Plugins.csproj file:
<ItemGroup>
<None Include="bin\Debug\netstandard2.0\Plugins.dll" Pack="true" PackagePath="Plugins"></None>
//add any output files from Plugins project which you want them to be packed
<None Include="build\Plugins.props" Pack="true" PackagePath="build"></None>
</ItemGroup>
use Pack Button to create the new release version of your nuget pakckage.
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.
When you finish the installing process, please click Build button and the files will generated under Plugins folder.
There is also a similar issue about this.

include the XML documentation from a NuGet package

I have a NuGet package with an xml documentation file (doc.xml).
I have installed the NuGet package in my project.
I know want to add the NuGet documentation file doc.xml to my solution.
I am running .net core 3.1 but I have no idea how this can be achieved.
Thank you!
If your nuget project is net standard or net core, please check these steps:
1) create a file called <package_id>.props file under a folder called build on your project.
Note that, you should make sure that the your package_id of your nuget project is the same as the .props file, otherwise, it will not work. See this link's description.
In my side, my nuget package called test.1.0.0.nupkg, so I should rename the file as test.props file.
2) please add these content in test.props file.
<Project>
<Target Name="CopyFilesToProject" BeforeTargets="Build">
<ItemGroup>
<SourceScripts Include="$(MSBuildThisFileDirectory)..\File\*.*"/>
</ItemGroup>
<Copy
SourceFiles="#(SourceScripts)"
DestinationFolder="$(ProjectDir)"
/>
</Target>
</Project>
The propose of this target is to copy the xml file from the File folder of the nupkg into the target project's folder when you install this nuget into the main project.
3) add these under xxx.csproj file:
<ItemGroup>
<None Include="bin\Debug\netcoreapp3.1\test.xml(the path of the xml file in your nuget project)" Pack="true" PackagePath="File"></None>
<None Include="build\test.props(the path of the test.props file in your nuget project)" Pack="true" PackagePath="build"></None>
</ItemGroup>
4) Then, when you pack your project, the structure should be this:
Before you install this new version of nuget package, you should clean nuget caches first or just delete all cache files under C:\Users\xxx(current user)\.nuget\packages to remove the old ones in case you still install the old one.
After that, rebuild your main project to execute the target and you will see the xml document file exist under the main project folder.
In addition, there is a similar issue you can refer to and if you use the net framework project, the link also provide the method.
===========================
Update 1
If you want to copy the file into bin\Release or bin\Debug, you should modify step 2, change to use this in the .props file:
<Copy
SourceFiles="#(SourceScripts)"
DestinationFolder="$(ProjectDir)$(OutputPath)"
/>
or just
<Copy
SourceFiles="#(SourceScripts)"
DestinationFolder="$(OutDir)"
/>
as you want.
Before you install this new version, you should first delete nuget caches under C:\Users\xxx(current user)\.nuget\packages.

Visual Studio / msbuild CopyToOutputDirectory - how does it work?

I am using Visual Studio Community:
Microsoft Visual Studio Community 2019
Version 16.4.5
VisualStudio.16.Release/16.4.5+29806.167
Microsoft .NET Framework
Version 4.8.03752
I have a very simple ASP.Net Core website / app project, with the following directory structure:
website
/bin
/www
/about
/images
NOTE: The webroot directory is NOT wwwroot, but instead just www
The project file (.csproj) contains the following (to copy all sub-directories/files to the output directory):
<ItemGroup>
<Content Update="www\**\*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
Using Visual Studio (Config = Debug)
BUILD -> Rebuild Solution
Result:
/bin
/Debug
/netcoreapp3.0
/Properties
/runtimes
(missing /www and all sub-directories and files!) - WHY???
The same results are obtained if I use msbuild.exe from the developer command prompt; makes no difference with regard to configuration (Debug vs Release).
I assumed that the www directory (and all sub-directories) and files would be copied to the output directory -- but clearly, this is not happening. I do not understand why the CopyToOutputDirectory is being ignored; I am missing something, but a search of the documentation did not yield any answers.
Any ideas / advice would be appreciated.
Thanks in advance.
Update:
Just changed the following in the project (.csproj) file:
<ItemGroup>
<Content Update="www\**\*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
To:
<ItemGroup>
<None Update="www\**\*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
Using Visual Studio: BUILD -> Rebuild Solution (success)
Also tried with msbuild.exe (success)
Now the www directory and all sub-directories / files are present in the output -- why? I suspect because I am not using the default "wwwroot" as the content directory, using <Content> does not work whereas <None> does; but that is only a theory; all I know is it works.
Also found this SO link useful in describing the differences between <Content> and <None>, for those who are curious:
What are the various "Build action" settings in Visual Studio project properties and what do they do?

Specify PackageFlatten for content files in Nuget package using Visual Studio 2017

I'm trying to get content files in a C#.Net project that is being packed into a Nuget package to flatten the containing folders. Based on this page it seems that this is possible with the flatten attribute.
But I want to use the new MSBuild Nuget packaging built into VS2017. Based on this page, I should be able to achieve the same thing with the <PackageFlatten> tag, but I cannot get it to work.
Here is a basic project file which demonstrates the problem. I'm expecting the single content file under the folder hierarchy .\RemoveMe\ContentFile.txt to end up in the Nuget package under .\content\ContentFile.txt - i.e. without the folder RemoveMe. But I still get this subfolder.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<Content Include="RemoveMe\ContentFile.txt">
<PackageFlatten>true</PackageFlatten>
</Content>
</ItemGroup>
</Project>
Specify PackageFlatten for content files in Nuget package using Visual Studio 2017
It should be a issue about argument flatten="true" for me. According to the document NuGet ContentFiles Demystified:
flatten - Should the files be all delivered to the root folder of the project or should they keep the folder structure that they were packaged in. The default value is false, which indicates they should create (if necessary) and keep the same structure they have after the TFM folder in the pacakge.
So if we set this argument flatten="true" in the .nuspec file, then pack this .nuspec, install the generate nuget package to the project, the file should be delivered to the root folder of the project. But after install this package to project, still got the that file in the sub-folder RemoveMe not in the root folder.
I also test other arguments buildAction="content" copyToOutput="false", both of them works fine.
So it should be a issue for the argument flatten="true", I submit this issue on GitHub, you can track this issue.

Resources