dotnet core publish: include/exclude dir in output - msbuild

Given aspnet project with folders:
/
/sql
/WebApp
/Client
/wwwroot
/Views
On project.json I used
"publishOptions": {
"include": [
"..\\sql",
"wwwroot",
"Views",
"web.config"
]
}
And after dotnet publish there was sql, wwwroot and Views folders.
After migration to csproj (Microsoft.NET.Sdk.Web), I got
<None Update="..\sql\**\*;wwwroot\**\*;Views\**\*">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</None>
After msbuild15 /t:publish (cli not works for me) there is wwwroot, Views AND Client with only json files inside. Files from sql copied but flattened.
I also try to change it to:
<Content Include="..\sql\**" CopyToPublishDirectory="PreserveNewest" />
<Content Remove="Client\*" CopyToPublishDirectory="Never" />
and got same output.
How to remove Client and preserve folder structure for sql?

Update:
When using VS 2017 >= 15.3 or a .NET CLI version >= 2.0, there is a new feature that automatically adds Link metadata for a few known item types (including Content). This can be used like:
<Content Include="..\sql\**" LinkBase="sql" />
Original:
You can use this:
<ItemGroup>
<Content Remove="Client\**" />
<Content Include="..\sql\**" CopyToPublishDirectory="PreserveNewest" Link="sql\%(RecursiveDir)\%(Filename)%(Extension)" />
</ItemGroup>
The content include item's link metadata is a bit of hack to make MSBuild use the item's relative path as target path. This is because items outside of the "project cone" aren't considered in AssignTargetPath if they have no Link metadata (source).
Alternative to <Content Remove="..." /> you can also do this to still have the files inside VS:
<Content Update="Client\**" CopyToPublishDirectory="Never" />

Related

ASP.NET Core 6: copy external directory to the publish folder

How to copy the content of external directory to the publish folder when I do dotnet publish ?
I tried the following in the project config, but unfortunately this copies the content of documents-templates directory to the root of the publish directory, but I want the whole folder documents-templates to be copied with its contents.
Is there any way to set the destination folder name too ?
<ItemGroup>
<Content Include="D:\Workspace\OtherProject\documents-templates\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
I have tested in my local, and it works for me.
<ItemGroup>
<Parent Include="C:\Users\Admin\Desktop\Testimages\*.*" />
<EmbeddedResource Include="#(Parent)">
<Link>Resources\%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>

How to include a local DLL reference in to a nuget package when calling msbuild pack?

We have several projects that need to include a few static DLL. Therefore the project files include code like this:
<ItemGroup>
<Reference Include="..\_Solutions\dependencies\abc123.dll" />
<Reference Include="..\_Solutions\dependencies\def456.dll" />
<Reference Include="System.Web" />
</ItemGroup>
Expected:
We expected that the two dlls; abc123.dll and def456.dll would befound in the nupkg file.
Actual:
However, the nupkg doesn't include the abc123.dll nor the def456.dll files.
One can always include custom content in the nuget-package. Like this:
<ItemGroup>
<Content Include="$(OutputPath)\ReferencedLib.dll">
<Pack>true</Pack>
<PackagePath>lib\$(TargetFramework)</PackagePath>
</Content>
</ItemGroup>
If you target multiple frameworks:
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard1.6</TargetFrameworks>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);IncludeReferencedProjectInPackage</TargetsForTfmSpecificContentInPackage>
</PropertyGroup>
<Target Name="IncludeReferencedProjectInPackage" Condition="'$(IncludeBuildOutput)' != 'false'">
<ItemGroup>
<TfmSpecificPackageFile Include="$(OutputPath)\ReferencedLib.dll" PackagePath="lib/$(TargetFramework)" />
</ItemGroup>
</Target>
How to include a local DLL reference in to a nuget package when calling msbuild pack?
According the issue on the GitHub, this is currently not directly supported by NuGet.
The workaround I suggest is using the .nuspec file:
NuGet allows you to disable the automatic generation of the resulting
.nuspec file and automatic collection of files by setting the
property in your project, along with a
property that allows you to pass replacement tokens for parsing the
.nuspec file.
See Martin`s answer for details.

Pass parameter/property from publish profile to csproj file

I exclude some folders while building for development in .csproj file.
<ItemGroup>
<Content Remove="Production\**" />
<Compile Remove="Production\**" />
</ItemGroup>
I want to include those folders back in a "publish profile" but it does not work.
<ItemGroup>
<Content Include="Production\**" />
<Compile Include="Production\**" />
</ItemGroup>
So, how could i pass parameters from "publish profile" to build(.csproj) and prevent exclusion of those folders or include them back.
<ItemGroup Condition="'$(SOMEPARAM)'!='Production'">
<Content Remove="Production\**" />
<Compile Remove="Production\**" />
</ItemGroup>
So, i need to determine when build runs with "publish profile" in .csproj file and take according action.
I know it is possible with command line parameters but i want to use Visual Studio, not command line.
dotnet build /p:DeployOnBuild=true /p:PublishProfile=FolderProfile;SOMEPARAM=Production
Update:(Solution)
Check my answer below, it works fine when CopyToPublishDirectory used.
Update:(Another Solution)
Alternatively, when targets specified with same names, a target from publish file will override the target from project file so we could define what to include/exclude separately in project and publish files.
You can define any property inside a <PropertyGroup> in the publish profile and use it in a condition in the csproj's <ItemGroup>s.
This works beause the publish profile is imported into the project and msbuild evaluates all static property groups before all item groups, which means that even a file that is imported at the end of it can affect item groups logically above it.
Sometimes my projects have "similar" code but hard-coded limitations like features supported by the operating system or license features.
I have solved it using 2 "configurations", let me walk you through it
Step 1. define your compiler directive in a central location where you need it in your code like so:
Console.WriteLine("Hello, World!");
#if IDPSH1
Console.WriteLine("IDPS H 1");
#elif IDPSH3
Console.WriteLine("IDPS H 2");
#elif IDPSH5
Console.WriteLine("IDPS H 3");
#endif
Console.ReadKey();
Step 2, in your build process, generate a build that would tell the compiler to generate what you need where you need it
dotnet publish ConsoleDefineConstants.csproj --output bin\release\IDPS-H-1 --configuration Release /p:DefineConstants=IDPSH1
dotnet publish ConsoleDefineConstants.csproj --output bin\release\IDPS-H-2 --configuration Release /p:DefineConstants=IDPSH2
dotnet publish ConsoleDefineConstants.csproj --output bin\release\IDPS-H-3 --configuration Release /p:DefineConstants=IDPSH3
In the sample, I instruct dotnet to build and publish
the relative project ConsoleDefineConstants.csproj
in release mode
using a compiler constant using the /p:DefineConstants=
in a location where my deployment packaging expects it
if I start the sample, I get
I added all the code you need in the sample, let me know if you like me to clarify something
So, i determined that those includes need CopyToPublishDirectory. So following works fine too.
In .csproj file;
<ItemGroup>
<Content Remove="Production\**" />
<Compile Remove="Production\**" />
</ItemGroup>
In publish profile;
<ItemGroup>
<Content Include="Production\**" CopyToPublishDirectory="PreserveNewest" />
<Compile Include="Production\**" CopyToPublishDirectory="PreserveNewest" />
</ItemGroup>

Views not being copied when publish the project in netcore 2.0 visual studio 2017

I have createa a ASP.NET Core 2.0 project in VS 2017. When I publish my project the Views folder are not there but the wwwroot folder is.
This I can setup in my .csproj file with the following:
<ItemGroup>
<Content Update="appsettings.json;web.config" CopyToOutputDirectory="PreserveNewest"/>
<Content Update="Views\**\*" CopyToOutputDirectory="PreserveNewest" />
<Content Update="wwwroot\**\*" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
but didn't work.
ASP.NET Core MVC has a precompilation feature, that could be added by referencing the Microsoft.AspNetCore.Mvc.Razor.ViewCompilation package. Feature enabling/disabling configured by MvcRazorCompileOnPublish property is .csproj.
And by default, the package is added in ASP.NET Core 2.0 MVC applications:
If you're targeting ASP.NET Core 2.0 or higher on netcoreapp2.0, a reference to the Microsoft.AspNetCore.Mvc.Razor.ViewCompilation package is added by Microsoft.AspNetCore.All and you do not need to explicitly reference it.
and precompilation is enabled:
The ASP.NET Core 2.x project templates implicitly set MvcRazorCompileOnPublish to true by default, which means this node can be safely removed from the .csproj file:
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<MvcRazorCompileOnPublish>true</MvcRazorCompileOnPublish>
</PropertyGroup>
If you go to publish output folder, you will see dll like <project_name>.PrecompiledViews.dll which contains your views.
In .NET Core 3.1 or later, we need to add the following code in .csproj:
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<CopyRazorGenerateFilesToPublishDirectory>true</CopyRazorGenerateFilesToPublishDirectory>
</PropertyGroup>
According to the docs:
When true, copies RazorGenerate items (.cshtml) files to the publish directory. Typically, Razor files aren't required for a published app if they participate in compilation at build-time or publish-time. Defaults to false.
It might be generating <project_name>.Views.dll by default. You need to set MvcRazorCompileOnPublishproperty false in your project .csproj file. By default it is true.
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish>
</PropertyGroup>
On 3.1, I have tried all of the above with no .cshtml files appearing. Interesting, I do get .cs files copied across to publish folders. i.e. in my csproj, the first two work - the other does not
<ItemGroup>
<Compile Update="Pages\AisLayout.cs">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Compile>
<Compile Update="Pages\Application.cs">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Compile>
</ItemGroup>
<ItemGroup>
<Content Update="Pages\ApplicationState.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="Pages\Cookies.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
If I manually copy the files, I am able to modify them with dynamic recompile occurring (as expected). Note: The .cshtml has no code behind files (long story).
More suggestions?

Delete folders from the publish output on an ASP.NET Core 1.1 project

I have an ASP.NET Core 1.1 project with the following in the csproj file:
<ItemGroup>
<Compile Include="**\*.cs" />
<EmbeddedResource Include="**\*.resx" />
</ItemGroup>
One of the Nuget packages included in the project adds a few localization folders to the publish output, e.g.: 'en', 'pt', 'fr', ...
I need to delete theses folders from the publish folder.
How can I do this?
I believe what you want is to use one or more None elements using the Exclude attribute, e.g. <None Exclude="en\**\*;pt\**\*;fr\**\*"/> You may also be able to use a Folder element and the Exclude element, e.g. Folder Exclude="en; pt;fr"/>.
enter link description here