build project without runtimes folder but included nuget packages in nopcommerce 4.40(.net 5 and VS 2019) - visual-studio

I'm developing plugin for nopcommerce,
I'm using VS 2019 and nopcommerce 4.40.4(.net 5)
I should use a nuget package in my plugin,
If I set CopyLocalLockFileAssemblies to true, when I build my project, it created runtimes folder, which is about 65 MB,
If I set CopyLocalLockFileAssemblies to false, it does not create runtimes folder, but, the dll of nuget package which I should use, not included in the build folder,
would you please help me about this?
Note: set copy local to no, make no difference when I change for Nop.Services which I use in the project
this is my csproj and my the package is > SmsIrRestful.NetCore :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<OutputPath>..\..\Presentation\Nop.Web\Plugins\AttributeStockSMS</OutputPath>
<OutDir>$(OutputPath)</OutDir>
<!--Set this parameter to true to get the dlls copied from the NuGet cache to the output of your project.
You need to set this parameter to true if your plugin has a nuget package
to ensure that the dlls copied from the NuGet cache to the output of your project-->
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<ItemGroup>
<ClearPluginAssemblies Include="$(MSBuildProjectDirectory)\..\..\Build\ClearPluginAssemblies.proj" />
</ItemGroup>
<ItemGroup>
<None Remove="plugin.json" />
</ItemGroup>
<ItemGroup>
<Content Include="plugin.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="SmsIrRestful.NetCore" Version="1.1.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Libraries\Nop.Services\Nop.Services.csproj">
<Private>false</Private>
</ProjectReference>
</ItemGroup>
<Target Name="NopTarget" AfterTargets="Build">
<!-- Delete unnecessary libraries from plugins path -->
<MSBuild Projects="#(ClearPluginAssemblies)" Properties="PluginPath=$(MSBuildProjectDirectory)\$(OutDir)" Targets="NopClear" />
</Target>
</Project>

Instead of using NuGet reference, include the dll file of that NuGet package. For example, You are going to use TaxJar library then follow these steps.
Added NuGet reference.
Right click on NuGet package and go to properties.
Copy path value from property values as below.
Go to that path in file explorer.
Find dll file(s) from there, copy-paste into your plugin folder and add refence.
Repeat same procedures for dependent packages also (if any).
Mark as Copy Local to Yes from properties.

Related

Create nuget package that references referenced .dlls without using .nuspec

Problem: Top level project references MyLibrary nuget which references several vendor.dll files. Vendor.dll files should be able to be referenced by top level project when MyLibrary nuget package is added to top level project but they are not.
When I run the top level project I receive this error:
FileNotFoundException: Could not load file or assembly 'Vendor.A, Culture=neutral, PublicKeyToken=b88d1754d700e49a'. The system cannot find the file specified.
Vendor .dll files are not copied to bin folder.
I hope to find a resolution to this problem that does not require me to create a .nuspec file.
Structure of generated MyLibrary nuget package (observed with Nuget package explorer):
lib
net5.0-windows
Vendor.a.dll
Vendor.b.dll
net5.0-windows7.0
MyLibrary.dll
I do not understand where net5.0-windows7.0 comes from. It does not exist in TFM list referenced below. Also, if net5.0-windows7.0 is for some reason necessary, why does MyLibrary.dll exist there but not the .dlls it depends on?
Looking at the package from within Visual Studio 2019 it appears as follows (vendor dlls do not appear):
Packages
MyLibrary
Compile Time Assemblies
MyLibrary.dll
MyLibrary.csproj:
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup>
<AssemblyVersion>1.0.0.1</AssemblyVersion>
<FileVersion>1.0.0.1</FileVersion>
<Version>1.0.0.3</Version>
</PropertyGroup>
<ItemGroup>
<Content Include="$(OutputPath)\Vendor.*.dll">
<Pack>true</Pack>
<PackagePath>lib\$(TargetFramework)</PackagePath>
</Content>
</ItemGroup>
<ItemGroup>
<Reference Include="Vendor.a">
<HintPath>VendorLib\Vendor.a.dll</HintPath>
</Reference>
<Reference Include="Vendor.b">
<HintPath>VendorLib\Vendor.b.dll</HintPath>
</Reference>
</ItemGroup>
TopLevel.csproj
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MyLibrary" Version="1.0.0.3" />
</ItemGroup>
Target Framework Monikers
Similar question
Similar question requiring nuspec
Similar question requiring nuspec
Possibly related issue
I also found an issue about this strange behavior and still did not know where the net5.0-windows7.0 from. Since the issue is still open and the Team does not know it is normal or a strange issue, as my opinion, net5.0-windows7.0 is the special version for wpf project's frameowork of nuget, so you should pack your dlls into such folder of nupkg.
Although this is not the best function, but is a workaround now. You can keep tracking the issue to get the explanation from the Product Team.
Or try my suggestions:
function one
1) change the targetframwork of your nuget project to
<TargetFramework>net5.0-windows7.0</TargetFramework>
As the Team said, net5.0-windows is the same as net5.0-windows7.0. However, they treat them differently in terms of packaging into nuget.
function two
2) still use <TargetFramework>net5.0-windows</TargetFramework>.
change this to:
<ItemGroup>
<Content Include="$(OutputPath)\Vendor.*.dll">
<Pack>true</Pack>
<PackagePath>lib\$(TargetFramework)7.0</PackagePath>
</Content>
</ItemGroup>
Besides, when you finish packing nuget project, please delete nuget caches first or delete all files under C:\Users\xxx\.nuget\packages, then install the new release version of the nuget package into the main project.
vendor is my custom nuget project name.

Msbuild pack ignores nuget packages with targets and task

I have ProjectA and ProjectB
ProjectA
Is a dotnet standard project with output and exe file to be used as as tool.
This generates a nuget package on build, using property and property to mark the package as a tool.
It also is marked as to auto exclude from projects which installs the nuget package, when they them also generate a nuget package.
<Project Sdk="Microsoft.Net.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<AssemblyName>ProjectA</AssemblyName>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IsTool>true</IsTool>
<DevelopmentDependency>true</DevelopmentDependency>
</PropertyGroup>
<ItemGroup>
<None Include="build\ProjectA.props" Pack="True" PackagePath="build" />
<None Include="build\net461\ProjectA.targets" Pack="True" PackagePath="build" />
</ItemGroup>
<PropertyGroup>
</Project>
ProjectA.targets
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<GetPackageVersionDependsOn>MyCustomTask;$(GetPackageVersionDependsOn)</GetPackageVersionDependsOn>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<Target Name="MyCustomTask">
<!-- Idealy i would use a custom task to set PackageVersion to something different. Like 5.0.99-alpha1+102435 -->
<PropertyGroup>
<PackageVersion>5.0.99-alpha1+102435</PackageVersion>
</PropertyGroup>
</Target>
</Project>
ProjectB
Installs a reference to the nuget package created by ProjectA.
<PropertyGroup>
<TargetFrameworks>net461</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ProjectA" Version="1.0.0" PrivateAssets="all" />
</ItemGroup>
When building ProjectB, the following files are genearted in obj/ folder:
.csproj.nuget.g.props
.csproj.nuget.g.targets
These files include import to ProjectA targets and props from the nuget package cache at:
%userprofile%.nuget\projecta\1.0.0\build\ProjectA.targets etc
Msbuild -t:pack ignores these imports when running, and hence the build ProjectB never sets the PackageVersion to 5.0.99-alpha1+102435 as i would expect.
Adding the above content of ProjectA.targets directly into ProjectB.csproj works.
Anyone have any suggestions what I'm missing or if the might be an issue?
If you use *.targets to pack the nuget project into a nuget package based on that file, you should make this file recognized along with csproj file.
Based on the description, it seems that you used that targets file to pack your nuget project into a version 5.0.99.
So you should make your csproj to work along with that file like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<!--the path of the *.targets file-->
<Import Project="xxx\xxx.targets"/>
</Project>
Update 1
clean nuget caches or delete all files under C:\Users\xxx\.nuget\packages) and msbuild -t:pack ProjectB.csproj to check it.
Update 1
Instead, modify Project B.csproj file:
use <TargetFramework>net461</TargetFramework> instead of <TargetFrameworks>net461</TargetFrameworks>.
The multi-platform framework seems to break the performance of the targets file, I'm also curious why this is happening. But this is the tip. You should use that.

Pick wwwroot/_content/ files from 3rd party Blazor library when publishing

I have an ASP.NET core 5 project that references some 3rd party Blazor libraries.
When I publish the project, it includes a lot of static asset files in $publishDir/wwwroot/_content/LiraryName/ folder, which is slowing down deployment. I don't need them all.
Is it possible to configure, which files should be skipped while publishing?
There is an easier way:
Just use these:
<ItemGroup>
<Content Update="wwwroot\_content\LiraryName\*.*">
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</Content>
</ItemGroup>
Before using it, please first delete the publish folder.
================
Update 1
Solution One
1) add GeneratePathProperty="true" into the nuget package reference node to generate the msbuild property PkgBlazored_Toast to access the content of the nuget package like this:
<ItemGroup>
<PackageReference Include="Blazored.Toast" Version="3.1.2" GeneratePathProperty="true" />
</ItemGroup>
2) add this:
<Target Name="RemoveTheFiles" AfterTargets="ComputeFilesToPublish">-->
<ItemGroup>
<ResolvedFileToPublish Remove="$(PkgBlazored_Toast)\staticwebassets\*.*"></ResolvedFileToPublish>
</ItemGroup>
</Target>
Also, first,delete the previous publish folder and then run the publish.
Solution Two
1) use Delete Task:
<Target Name="RemoveTheFiles" AfterTargets="AfterPublish">
<PropertyGroup>
<Folder>$(PublishUrl)wwwroot\_content</Folder>
</PropertyGroup>
<RemoveDir Directories="$(Folder)"></RemoveDir>
</Target>
I have my NPM folder --> NpmJS inside wwwroot
Edit the csproj file like this:
Works like a charm.
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="npm install" WorkingDirectory="wwwroot\NpmJS" />
<Exec Command="npm run build" WorkingDirectory="wwwroot\NpmJS" />
</Target>

Package third party dll in context of multi target framework project, .Net Framework & .Net Core

I'm using next configuration within csproj :
<ItemGroup Condition="$(TargetFramework.StartsWith('net4'))">
<Reference Include="amqmdnet">
<HintPath>..\bin\amqmdnet.dll</HintPath>
</Reference>
<Content Include="..\bin\amqmdnet.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<Pack>true</Pack>
<PackagePath>lib\$(TargetFramework)</PackagePath>
</Content>
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('netstandard2')) or $(TargetFramework.StartsWith('netcoreapp3'))">
<Reference Include="amqmdnetstd">
<HintPath>..\bin\amqmdnetstd.dll</HintPath>
</Reference>
<Content Include="..\bin\amqmdnetstd.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<Pack>true</Pack>
<PackagePath>lib\$(TargetFramework)</PackagePath>
</Content>
</ItemGroup>
each part of it working fine when the project is set with a concrete framework, for example :
<TargetFramework>netcoreapp3.1</TargetFramework>
but when the project is multi framework noting happened, dlls are not included
<TargetFrameworks>netcoreapp3.1;net451</TargetFrameworks>
I'm getting this message in multi framework scenario, this is the only context:
How I proceeded
For some reason nuget spec doesn't fill metadata; I test it with nuget version 5.5.1.6542.
I build the project with VS, how it is.
Change extension of {project folder}\bin\Release\xxx.nupkg to .zip
Extract xxx.nuspec file from xxx.zip. It will contain also dependencies metadata.
Edit xxx.nuspec with NuGet Package Explorer
Build nuget xxx.nuspec
.nuspec documentation
Answer
See this link. NuGet doc
I will post it and here:
<PropertyGroup>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);GetMyPackageFiles</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<Target Name="GetMyPackageFiles">
<ItemGroup Condition="$(TargetFramework.StartsWith('net4'))">
<BuildOutputInPackage Include="amqmdnet.dll">
<FinalOutputPath>..\bin\amqmdnet.dll</FinalOutputPath>
</BuildOutputInPackage>
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('netstandard2')) or $(TargetFramework.StartsWith('netcoreapp3'))">
<BuildOutputInPackage Include="amqmdnetstd.dll">
<FinalOutputPath>..\bin\amqmdnetstd.dll</FinalOutputPath>
</BuildOutputInPackage>
</ItemGroup>
</Target>
Package third party dll in context of multi target framework project,
.Net Framework & .Net Core
I tried your sample and face the same issue in my side. When I use TargetFrameworks to set such dll into multi target framework projects and face the same situation.
And the <pack>true</pack> does not work due to your condition. But when I looked into output folder in such project, <CopyToOutputDirectory>Always</CopyToOutputDirectory> works. And according to the conditions, copy the two types of dll to the corresponding target framework folder.
However, pack does not work,still quite be strange.
So l report this issue to our DC Forum. See this link. You can vote this issue and add any comments if I did not describe the issue in detailed. And anyone who is interested in this issue will vote for you so that it will get more attention from the staff.
Suggestion
As a suggestion, you can use nuspec file with nuget.exe cli to pack your project which I have tested successfully.
1) download nuget.exe from this link and config its path into System Environment Variable PATH.
2) call Developer Command Prompt for VS or CMD and then cd your project path(which xxx.csproj exists)
Then call nuget spec and get xxx.nuspec file
3) open xxx.nuspec file and modify like these:
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata>
......
</metadata>
<files>
<file src="bin\Debug\net451\amqmdnet.dll" target="lib\net451" />
<file src="bin\Debug\net451\PRCB.IBM.MQ.dll" target="lib\net451"/>
<file src="bin\Debug\netcoreapp3.1\amqmdnetstd.dll" target="lib\netcoreapp3.1" />
<file src="bin\Debug\netcoreapp3.1\PRCB.IBM.MQ.dll" target="lib\netcoreapp3.1" />
</files>
</package>
4) Finally, type nuget pack xxx.nuspec and you will get the xxx.nupkg file.

PackageReference condition is ignored

In my VS 2017 project I reference docfx.console package and I want it to be used only when certain condition is met. But the package gets used for all builds.
Here is a part of my project. I want docfx.console to be used when configuration is Installer/AnyCPU and VS is building net40 flavor.
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net40;netstandard1.3;netstandard2.0</TargetFrameworks>
<!-- ... -->
<Configurations>Debug;Release;Installer</Configurations>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)'=='net40' ">
<!-- ... -->
<PackageReference Include="docfx.console" Version="2.30.0" Condition="'$(Configuration)|$(Platform)'=='Installer|AnyCPU'" />
</ItemGroup>
<!-- ... -->
</Project>
Is there a way to use docfx.console in Installer build for net40 only?
To summarize, even with the condition "false", the package will be imported.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp3.0;netcoreapp2.2;net472</TargetFrameworks>
<Platforms>x64;x86</Platforms>
</PropertyGroup>
<ItemGroup Condition="false">
<PackageReference Include="MyPackage" Version="1.0.0" />
</ItemGroup>
</Project>
We found that we can work around this issue by putting the packagereference in a different file, and making the import of the file conditional.
Separate file: packagerefs.targets
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="MyPackage" Version="1.0.0" />
</ItemGroup>
</Project>
Project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp3.0;netcoreapp2.2;net472</TargetFrameworks>
<Platforms>x64;x86</Platforms>
</PropertyGroup>
<Import Project="packagerefs.targets" Condition="false" />
</Project>
Even i was looking for referencing nuget packages on condition based (load only when expected constant is set in DefineConstants). Though #Luke Schoen Solution worked for me, I could make it work without the external targets file.
Solution is to include your PackageReference using Choose > When
Make sure to have this block after your PropertyGroup which has DefineConstants.
<Choose>
<When Condition="$(DefineConstants.Contains('My_CONST'))">
<ItemGroup>
<PackageReference Include="MyPackage">
<Version>1.0.6</Version>
</PackageReference>
</ItemGroup>
</When> </Choose>
PackageReference condition is ignored
This is an known issue about the new style csproj PackageReference to work with content/Tools files in a nuget package.
In the package docfx.console, it looks like docfx.console has "content", "build" and "tools" without .NET code in it, just random files:
In this case, when we install this nuget package, nuget does not do anything. So it seems gets used for all builds. That because:
NuGet packages that work with Packages.config, don't always work in
transitive NuGet environments (projects using Project.json or
PackageReferences). Packages that work in transitive NuGet
environments must use "contentFiles" instead of "content" -- you can
have both, if a package would like to work in both environments. Also,
install.ps1/uninstall.ps1 doesn't execute in transitive NuGet
environments -- however, init.ps1 will work in both Packages.config
and transitive environments.
At this moment, there is not a perfect solution, so the issue 4837 is still open.
To resolve this issue, the NuGet docfx.console package needs to be changed to use contentFiles and define targets and would typically reference a tool by using $(MSBuildThisFileDirectory)..\tools\MyTool.exe. If you put this PackageName.targets file into the a build directory, it will be automatically included into the project referencing the NuGet package.
Hope this helps.
In my case I had also same kind of problem - but root cause was that some of msbuild properties were not defined when nuget package building was performed - in particular $(SolutionName) was not defined. Condition still gets evaluated, only it's returning true for some reason. (You can test this by putting Condition="false" - it will be omitted).
Solution for me was to check if property is defined, for example like this:
<ItemGroup Condition="'$(SolutionName)' != '' and $(SolutionName.Contains('SolutionCustomTag'))">
<Reference Include="...">
Te first statement '$(SolutionName)' != '' and - tests that property is defined.

Resources