Why does dotnet build not include folders when running release? - asp.net-core

I am trying to build a .net core 3 Web App in release mode, but the folders wwwroot and ClientApp are missing from the published source.
I tried adding them manually to the .csproj like below, and the folders get included but none of the content in them.
Any ideas?
<ItemGroup>
<None Include="ClientApp\*" />
<None Include="wwwroot\*" />
</ItemGroup>

You can try the ** wildcard to include everything in these folders. The documentation states:
The ** wildcard character sequence matches a partial path.
So your ItemGroup would look like this:
<ItemGroup>
<None Include="ClientApp\**" />
<None Include="wwwroot\**" />
</ItemGroup>

Related

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.

.NET Core 1.1 - getting "Duplicate 'Content' items were included"

I've updated my VS2017 to latest 15.3.0 and installed .NET Core SDK 2.0 (I would like to upgrade an existing .NET 1.1 application to 2.0).
Now when I open my project that was compiling fine (didn't change anything in it yet) and I try to compile I get:
Duplicate 'Content' items were included.
The .NET SDK includes 'Content' items from your project directory by default.
You can either remove these items from your project file, or set the 'EnableDefaultContentItems' property to 'false' if you want to explicitly include them in your project file.
For more information, see https://aka.ms/sdkimplicititems. The duplicate items were: 'wwwroot\index.html'
Under problematic file it's pointing to C:\Program Files\dotnet\sdk\2.0.0\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.Sdk.DefaultItems.targets
I've read online and I'm able to solve this by adding <EnableDefaultContentItems>false</EnableDefaultContentItems> to my .csproj file. But it wasn't there before and I'm not sure what adding this line means.
Once thing that really bothers me is that the source file it's pointing to is in dotnet\sdk\2.0.0 - and as I mentioned the project is still .NET Core 1.1. All I did so far was to install the update for VS2017 and the 2.0 SDK.
How do I solve this? I would like my original project to compile before I upgrade it to 2.0.
EDIT
My csproj file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Content Include="wwwroot\index.html" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="IdentityServer4" Version="1.5.2" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.1" />
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.2" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.4.1" />
</ItemGroup>
<ItemGroup>
<Content Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="web.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Update="NLog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
As mentioned if I add <EnableDefaultContentItems>false</EnableDefaultContentItems> to PropertyGroup it works. But I don't know what is the meaning of this or why it's needed all of a sudden...
Remove the <ItemGroup> element containing
<Content Include="wwwroot\index.html" />
This item is already included by the Microsoft.NET.Sdk.Web and is therefore defined twice.
Necromancing.
Alternatively, do the following:
Click 'Show All Files' in Solution Explorer
Right click over 'wwwroot' select 'Exclude From Project'
Right click over 'wwwroot' select 'Include in Project'
The error is now gone.
Much safer than editing by hand.

AjaxMin task has been declared or used incorrectly, or failed during construction

I'm trying to add Microsoft's AjaxMin to VS2012 project and I'm not really sure what I'm doing. I think I'm missing something obvious.
I copied the code from the tutorial here (http://ajaxmin.codeplex.com/wikipage?title=AjaxMinTask)
And I've tried adding the reference to my project so my code looks like this:
<UsingTask TaskName="AjaxMin" AssemblyFile="$(MSBuildProjectDirectory)\Build\AjaxMinTask.dll" />
<Target Name="AfterBuild" >
<ItemGroup>
<JS Include="**\*.js" Exclude="**\*.min.js;Scripts\*.js" />
</ItemGroup>
<ItemGroup>
<CSS Include="**\*.css" Exclude="**\*.min.css" />
</ItemGroup>
<AjaxMin JsSourceFiles="#(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".min.js" CssSourceFiles="#(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".min.css" />
</Target>
This is at the bottom of my .csproj file where there was already a commented out AfterBuild section. I get errors saying JS, CSS, AjaxMin are invalid child elements. When I try to build the project I get an error, I'm not sure what I am missing. I created a folder in the project called Build and added the AjaxMinTask.dll. I don't know if there's any additional thing i need to do to make sure it is referenced properly.
I've also tried using the Import node instead of the UsingTask
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\AjaxMin.tasks" />
And I think AjaxMin is installed correctly because I can run it from command line.
In your .csproj, the end of the document (I've included the last closing element ) should look something like this:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\MicrosoftAjax\AjaxMin.tasks" />
<Target Name="AfterBuild" AfterTargets="CopyAllFilesToSingleFolderForPackage" Condition="'$(Configuration)'=='Release'">
<ItemGroup>
<JS Include="scripts\*.js" Exclude="scripts\*.min.js;" />
</ItemGroup>
<ItemGroup>
<CSS Include="css\main.css" />
</ItemGroup>
<AjaxMin Switches="-global:jQuery,$" JsSourceFiles="#(JS)" JsCombinedFileName="scripts\combined.min.js" CssSourceFiles="#(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".min.css" />
</Target>
</Project>
As I am using Windows 7 64-bit, you will see the path of Import... includes (MSBuildExtensionsPath32). If you are using Windows 32-bit, then you do not need the 32 at the end. Other then that, your code should work.
Disregard the JS, CSS, AjaxMin childelements error. But you should not get a built error. If you could post your built error, it would be useful.
Also, the code above combines multiple JS files, just added for fun.

Trying to include a transformed App.config in a XAP file

I have a Silverlight project with multiple configuration files, and am using the transformation approach shown here:
App.Config Transformation for projects which are not Web Projects in Visual Studio 2010?
This approach doesn't work as-is for Silverlight projects though. I've re-written the MSBuild project to look like this:
<ItemGroup>
<None Include="App.config" />
<None Include="App.QABuild.config">
<DependentUpon>App.config</DependentUpon>
</None>
</ItemGroup>
....
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="BeforeCompile" Condition="Exists('App.$(Configuration).config')">
<!-- Generate transformed app config in the output directory -->
<Message Importance="high" Text="Transforming 'App.$(Configuration).config' to output config file..." />
<TransformXml Source="App.config" Destination="$(OutputPath)App.config" Transform="App.$(Configuration).config" />
<ItemGroup>
<Content Include="$(OutputPath)App.config" />
</ItemGroup>
</Target>
<Target Name="BeforeCompile" Condition="!Exists('App.$(Configuration).config')">
<Message Importance="high" Text="Using default 'App.config' as output config file..." />
<Copy SourceFiles="App.config" DestinationFiles="$(OutputPath)App.config" />
<ItemGroup>
<Content Include="$(OutputPath)App.config" />
</ItemGroup>
</Target>
This code generates the correct output file for the correct configuration, however it is never included in the XAP file, even though I am putting the output config into the Content item group. All I need to happen is for the output config to get included in the output XAP but I can't get this to happen.
Can anyone tell me what I'm doing wrong? I'm not an MSBuild expert by any means!
Found the solution by digging into the Silverlight 4 targets. Turns out the XAP packager target actually takes an item called XapFilesInputCollection, which is where the input files come from. The Content item looks likes it is copied to this item before my target runs, so modifying the Content item afterwards is the wrong approach.
All I did was add the transformed files directly to the XapFilesInputCollection item and it worked as I expected.

MSBuild project file: Copy item to specific location in output directory

In the process of cleaning up the folder/file structure on a project I inherited, I'm running into a problem with organizing the required external libraries. I want to keep them in their own .\dll\ folder, but they're not being copied to the build directory properly. They should be in the root build directory, but they're being moved to a subfolder instead.
My .csproj file contains the following xml:
<Project>
<ItemGroup>
<None Include="dlls\libraryA.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Then, on build, the libraryA.dll file is copied to the bin\Debug\dll\ folder, but I want it in the bin\Debug\ folder.
I tried this and msbuild always wants to copy the files using their directory path, but there is a workaround...
Edit the csproj file and after this line:
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Add these lines:
<PropertyGroup>
<PrepareForRunDependsOn>$(PrepareForRunDependsOn);MyCopyFilesToOutputDirectory</PrepareForRunDependsOn>
</PropertyGroup>
<Target Name="MyCopyFilesToOutputDirectory">
<Copy SourceFiles="#(None)" DestinationFolder="$(OutDir)" />
</Target>
The copy of the output files happens in the PrepareForRun target. This adds your own target to the list of targets that are executed as part of PrepareForRun.
This example copies all items in the None item group. You could create your own item group (e.g. MyFiles) and do the copy on that item group if you have other "None" files you don't want copied. When I tried this I had to change the item group name by editing the csproj file directly. Visual Studio did not allow me to set the item group of a file from the UI, but after I edited the csproj and changed it, Visual Studio displayed my custom item group name correctly.
If you only want to change it for one file, it may be easier to use the property:
<None Include="dlls\libraryA.dll">
<Link>%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Including content files in .csproj that are outside the project cone
This approach works
If you need to force copy of a specific file/nuget package into an asp.net core project (2.2), add at the end of your csproj :
<!-- Force copy MathNet because we need it in compilation -->
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="Build">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MathNet.Numerics.4.8.1\lib\netstandard2.0\MathNet.Numerics.dll')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MathNet.Numerics.4.8.1\lib\netstandard2.0\MathNet.Numerics.dll'))" />
</Target>
<ItemGroup>
<ContentWithTargetPath Include="..\packages\MathNet.Numerics.4.8.1\lib\netstandard2.0\MathNet.Numerics.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>MathNet.Numerics.dll</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
In SDK-style csproj you can write something like:
<Target Name="CopyFilesTargetName" AfterTargets="Build">
<Copy SourceFiles="$(OutDir)\dlls\Some.dll;$(OutDir)\dlls\SomeOther.dll" DestinationFolder="$(OutDir)" />
</Target>
You can also use <Move instead of <Copy to move files