Using dotnet pack creates NUGET with dependencies but without my own code - c#

I have a simple .NET Core 3.1 class library that implements some logging functionality inside classes and has a nlog.config file. The .csproj looks like this
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Library</OutputType>
<IsPackable>true</IsPackable>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<NuspecFile>Sima.Logging.nuspec</NuspecFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="4.7.12" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.3" />
</ItemGroup>
</Project>
As you can see, my .csproj references a .nuspec file. I need to do this because I want to include the nlog.config as a content file. The .nuspec looks like this
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Sima.Logging</id>
<version>1.0.0</version>
<contentFiles>
<files include="**/nlog.config" buildAction="Content" copyToOutput="true" flatten="true" />
</contentFiles>
<dependencies>
<group>
<dependency id="NLog" version="4.7.12" exclude="Build,Analyzers" />
<dependency id="NLog.Web.AspNetCore" version="4.9.3" exclude="Build,Analyzers" />
</group>
</dependencies>
</metadata>
<files>
<file src="contentFiles\**" target="contentFiles" />
</files>
</package>
After packaging my library using dotnet pack, the nupkg only includes the two dependencies to NLog, but none of my actual code (in my class) is included in the package.
It seems like NuGet doesnt know what to actually build. What did I miss?

When creating Nuget package (*.nupkg), you must define all files you want to be included in that package. In nuspec config you are missing following:
<files>
<file src="bin\Debug\*.dll" target="lib" />
</files>
Where bin\Debug\ is the output path of your build. For further reference please visit the documentation.

Related

Dotnet Pack vs Nuget.exe Pack, version downgrade error

We have changed from using nuget.exe pack, to dotnet pack (to get rid of the need for a .nuspec file)
We used to run this command:
nuget pack "MyComp.Shared\MyComp.Shared.csproj" -OutputDirectory c:\nugetlocal -version 2021.7.7.1149-local -symbols
And we would have no issues consuming this packed nuget in our local project during development.
Now instead we run
dotnet pack "MyComp.Shared\MyComp.Shared.csproj" -output c:\nugetlocal -version 2021.7.7.1149-local --include-symbols
However, when we consume this package we now get version downgrade errors. This didn't happen with nuget.exe packed, using the first command.
The error
Severity Code Description Project File Line Suppression State Tool
Error NU1605 Detected package downgrade: MyComp.Enums from 2021.7.7.1149-local to 2021.7.5.1317. Reference the package directly from the project to select a different version.
MyComp.Processors -> MyComp.Shared 2021.7.7.1149-local -> MyComp.Enums (>= 2021.7.7.1149-local)
MyComp.Processors -> MyComp.Enums (>= 2021.7.5.1317) MyComp.Processors C:\Users\uzzer\source\repos\MyCompp\MyComp.Processors\MyComp.Processors.csproj
The Nuget package project
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<PackageId>MyComp.Shared</PackageId>
<Description>MyComp.Shared</Description>
<Authors>MyComp</Authors>
<Company>MyComp</Company>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentValidation" Version="10.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="5.0.6" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="5.0.6" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyComp.Extensions\MyComp.Extensions.csproj" />
<ProjectReference Include="..\MyComp.Enums\MyComp.Enums.csproj" />
</ItemGroup>
</Project>
The consuming project
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MyComp.Enums" Version="2021.7.5.1317" />
</ItemGroup>
</Project>
EDIT: this link really helped solve the issue
To understand the issue,
You can take a .nupkg file, change the extension to .zip and then open the file. Inside is a .nuspec file.
When we packed with nuget.exe, this did not include anything in the <dependancies /> tag.
What we realized what that dotnet pack takes project references adds them to the internal .nuspec file, and version stamps them with the same version number as the project you are packing
So we need to make sure that when we build one, we build the dependencies and consume those too.
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>MyComp.Shared</id>
<version>2021.7.7.1150-local</version>
<authors>MyComp</authors>
<description>MyComp.Shared</description>
<dependencies>
<group targetFramework="net5.0">
<dependency id="MyComp.Enums" version="2021.7.7.1150-local" exclude="Build,Analyzers" />
<dependency id="FluentValidation" version="10.1.0" exclude="Build,Analyzers" />
<dependency id="Microsoft.AspNetCore.Identity" version="2.2.0" exclude="Build,Analyzers" />
<dependency id="Microsoft.AspNetCore.Identity.EntityFrameworkCore" version="5.0.6" exclude="Build,Analyzers" />
<dependency id="Microsoft.AspNetCore.Mvc.Abstractions" version="2.2.0" exclude="Build,Analyzers" />
<dependency id="Microsoft.AspNetCore.Mvc.ViewFeatures" version="2.2.0" exclude="Build,Analyzers" />
<dependency id="Microsoft.Extensions.Identity.Core" version="5.0.6" exclude="Build,Analyzers" />
<dependency id="Microsoft.Extensions.Identity.Stores" version="5.0.6" exclude="Build,Analyzers" />
<dependency id="Newtonsoft.Json" version="13.0.1" exclude="Build,Analyzers" />
</group>
</dependencies>
</metadata>
</package>

How to correctly specify dependency information in nuspec file while creating Nuget package?

I'm trying to create Nuget package from a Visual Studio 2017 class Library first time. It is a .NET Framework 4.6.2 project.
The class library is referencing some other nuget packages, dlls, exes which are in References section under Solution Explorer.
Here are the steps I took after looking at some youtube videos and Microsoft documentation:
Right click project and select Properties.
Build option, set Configuration to Release. Saved and closed project properties.
Opened csproj file and changed Configuration to Release
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
Now build the project in Release mode. I can see dlls under
MyProject\bin\Release and also under MyProject\bin\Debug
Then I create the spec file using
nuget spec
Opened it and made appropriate changes and then
nuget pack MyProject.nuspec
I am getting number of warnings like both for Debug and Release directory:
WARNING: NU5100: The assembly 'bin\Debug\Encryption.dll' is not inside the 'lib' folder and hence it won't be added as a reference when the package is installed into a project. Move it into the 'lib' folder if it needs to be referenced.
although the Class Library (which I am creating Nuget), has a packages.config and has references:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Encryption" version="1.1.0" targetFramework="net462" />
...
...
...
<package id="TeraData" version="16.20.8" targetFramework="net462" />
</packages>
Since I am getting warnings, I tried entering dependency information in the nuspec file. Here is what my nuspec file looks like
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata>
<id>ProjectTitle</id>
<version>1.0.0</version>
<title>ProjectTitle</title>
<authors>auther name</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>desc of package</description>
<releaseNotes>release notes text</releaseNotes>
<copyright>Copyright info</copyright>
<tags>some tages</tags>
<dependencies>
<dependency id="Encryption" version="1.1.0" />
...
<dependency id="TeraData" version="16.20.8" />
</dependencies>
</metadata>
</package>
But still get same warnings. If you can please provide a sample how dependency info in nuspec should look like, that would really help!
Please advise if I'm missing anything!
I think it's just a problem with the command of your nuget pack method.
We usually do not use nuget pack xxx.nusepc command to pack a nuget package because it cannnot pack the realated dll,pdb files including the main nuget project's dll automatically into the nupkg.
You have to write the whole nuspec node with it. You have to write <files> node in nuspec file to include your main project's dll so that it will remove the warning of missing dependencies. You should not add <references> node additionally.
like:
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata>
<id>ProjectTitle</id>
<version>1.0.0</version>
<title>ProjectTitle</title>
<authors>auther name</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>desc of package</description>
<releaseNotes>release notes text</releaseNotes>
<copyright>Copyright info</copyright>
<tags>some tages</tags>
<dependencies>
<dependency id="Encryption" version="1.1.0" />
...
<dependency id="TeraData" version="16.20.8" />
</dependencies>
</metadata>
<files>
<file src="bin\Release\ProjectTitle.dll" target="lib\net462" />
.....
</files>
</package>
Then, use nuget pack xxx.nuspec -Properties Configuration=Release command to pack it. You should pack the the main project' dll in this way. And if your project refences other assembly dlls or extra exe files.
You should add them:
<file src="bin\Release\extra_assembly.dll" target="lib\net462" />
<file src="bin\Release\extra_exe.exe" target="lib\net462" />
=========================================
However, this function is not very convenient. And we usually do not need them, we usually use this:
nuget pack xxx.csproj
Usually, we use nuget pack xxx.csproj -Properties Configuration=Release to pack without any other node. Before this, you should cd xxx\<project folder>.
use this nuspec file:
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata>
<id>ProjectTitle</id>
<version>1.0.0</version>
<title>ProjectTitle</title>
<authors>auther name</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>desc of package</description>
<releaseNotes>release notes text</releaseNotes>
<copyright>Copyright info</copyright>
<tags>some tages</tags>
<dependencies>
<dependency id="Encryption" version="1.1.0" />
...
<dependency id="TeraData" version="16.20.8" />
</dependencies>
</metadata>
<!--If you have any other referenced assembly dll files or pdb files, exe files, you should add them here.-->
<files>
.....
</files>
</package>
You should not add your main nuget project's dll with <file> node and it will add into your nupkg automatically with that command.
When you create the new release version of your nuget package, first uninstall the old one under your project, then delete all cache files under C:\Users\xxx\.nuget\packages. After that, reinstall the new release one in your new project.
Here is the nuspec file structure using .NET framework which finally worked for me:
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata>
<id>ClasslibProj </id>
<version>1.0.0.0</version>
<title> ClasslibProj</title>
<authors>author(s) name</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>desc</description>
<releaseNotes>release notes</releaseNotes>
<copyright>Copyright # Company name 2021</copyright>
<tags>tags to search </tags>
<references>
<group targetFramework=".NETFramework4.6.2">
<reference file="SomeOtherNugetpackage1.dll"/>
<reference file="anyexecutable.exe"/>
…
<reference file="ClasslibProj.dll"/> //dll you are working with
</group>
</references>
</metadata>
<files>
<file src="bin\Release\SomeNugetOtherpackage1.dll" target="lib\net20"/>
<file src="bin\Release\anyexecutable.exe" target="lib"/>
..
<file src="bin\Release\ClasslibProj.dll" target="lib\net462"/>
</files>
</package>
Build project in Release mode.
use command:
nuget pack ClasslibProj.csproj
As mentioned by Sara Liu, avoid using ClasslibProj.nuspec
or you may use detailed command:
nuget pack ClasslibProj.csproj -Properties Configuration=Release

Nuget package doesn't copy contentFiles specified in .nuspec

I have a custom nuspec file for a c# project. In this example, the project is supposed to produce a nuget package which has an exe and a folder with some extra content in it.
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>$id$</id>
<version>$version$</version>
<authors>$authors$</authors>
<description>$description$</description>
<contentFiles>
<files include="Program.exe" buildAction="Content" copyToOutput="true" />
<files include="Folder/**/*" buildAction="Content" copyToOutput="true" />
</contentFiles>
</metadata>
<files>
<file src="src\Program.exe" target="contentFiles"/>
<file src="src\Folder\**\*" target="contentFiles\Folder"/>
</files>
</package>
When I inspect the .nupkg, the files are all there inside of a contentFiles folder. However when I try and consume the package with a package reference
<PackageReference Include="MyPackage" Version="1.0.0" />
..the files don't actually end up in the output folder. It's probably a small issue but I can't seem to be able to find an answer. Any hints would be great.

Nuget: Including an exe as a Run-time dependency

I have an .exe app that I need to distribute with my C# app when it builds. I am trying to use Nuget to package it so that it will be included in the build root directory when building but am having trouble getting the behaviour I want.
Here is what I've got in my .nuspec file:
<?xml version="1.0"?>
<package>
<metadata>
<id>my.id</id>
<version>1.0.0</version>
<authors>me</authors>
<owners>me</owners>
<licenseUrl>myurl</licenseUrl>
<projectUrl>myurl</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>A copy of an .exe so we can easily distribute it
with our applications without needing to include it in our VCS repo</description>
<releaseNotes>Initial test version</releaseNotes>
<copyright>Copyright 2018</copyright>
<dependencies>
</dependencies>
<packageTypes>
</packageTypes>
<contentFiles>
<files include="any\any\myexe.exe" buildAction="None" copyToOutput="true" />
</contentFiles>
</metadata>
<files>
<file src="content\myexe.exe" target="content" />
</files>
</package>
This puts the myexe.exe file to my VS project when I install the Nuget Package but it does not copy the file when I build. What I'd like is for the file to by installed with my other app files when building and to keep it out of my VS project.
I've been reading docs here but am not sure how to make the nuspec file.
More Details:
Nuget 4.5.1
Visual Studio 2015
Note: the <files> and <contentFiles> might seem to be duplicating functionality. I'd like to employ both as I understand this will future-proof it for VS2017
Nuget: Including an exe as a Run-time dependency
First, I know you want to use some technologies for the future, but we have to know that these future-oriented technologies often have certain constraints and conditions.
For example, <contentFiles> is used for NuGet 4.0+ with PackageReference, neither of them is supported by Visual Studio 2015. See Using the contentFiles element for content files for some details.
If you are interested in the <contentFiles>, you can read the blog NuGet is now fully integrated into MSBuild.
Go back to our question now, according to above info, we should not use <contentFiles> when we use Visual Studio 2015. To resole this issue, we need to add a .targets file in the nuget package when you build the project:
The content of .targets file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="$(ProjectDir)myexe.exe">
<Link>myexe.exe</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CustomToolNamespace></CustomToolNamespace>
</None>
</ItemGroup>
</Project>
The .nuspec file like following:
<files>
<file src="build\YouNuGetPackageName.targets" target="build\YouNuGetPackageName.targets" />
<file src="content\myexe.exe" target="content\myexe.exe" />
</files>
Note: The name of the .targets file should be same as your nuget package name.
With this way, when you build your project, MSBuild/VS would copy the file myexe.exe to the output folder.
Besides, if you want to copy the file myexe.exe to other destination, you can replace the content of .targets file with a copy task, like:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CopyMyexe" BeforeTargets="Build">
<Message Text="Copy CopyMyexe to the folder."></Message>
<Copy
SourceFiles="$(ProjectDir)myexe.exe"
DestinationFolder="xxx\xxx\xx\myexe.exe"
/>
</Target>
</Project>
See Creating native packages and similar issue for some helps.
Hope this helps.

Including a non referenced dll from a package

I have a nuspec file that looks like this:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>MyDll.Service</id>
<version>1.0.0</version>
<title>MyDll.Service</title>
<authors>MyDll</authors>
<owners>MyDll</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Description</description>
<copyright>Copyright © 2017</copyright>
<dependencies>
<dependency id="SomeDll" version="1.0.0" />
</dependencies>
<references>
<reference file="MyDll.Service.Context.dll" />
</references>
</metadata>
<files>
<file src="..\..\Folder\MyDll.Service.Context\bin\Release\MyDll.Service.Context.dll" target="lib\net452"/>
<file src="..\..\Folder\MyDll.Service\bin\Release\MyDll.Service.dll" target="lib\net452"/>
</files>
</package>
This generates me a nuget package that contains 2 dlls. The project itself only references MyDll.Service.Context.dll (which is exactly what I want).
I am using injection to insert the MyDll.Service.dll wherever the classes for MyDll.Service.Context.dll are mentioned. My only problem is that when I build, the dll MyDll.Service.dll is not pulled into the bin folder of the main project. Only the MyDll.Service.Context.dll is. This makes sense because I only reference the context dll.
My question, how can I get MyDll.Service.dll pulled into the bin folder upon building and publishing the project, without having to reference that dll in the project?
EDIT:
As per suggestion in the comments I tried to do this with MSBuild. I changed my nuspec to the following:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>MyDll.Service</id>
<version>1.0.0</version>
<title>MyDll.Service</title>
<authors>MyDll</authors>
<owners>MyDll</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Description</description>
<copyright>Copyright © 2017</copyright>
<dependencies>
<dependency id="SomeDll" version="1.0.0" />
</dependencies>
<references>
<reference file="MyDll.Service.Context.dll" />
</references>
</metadata>
<files>
<file src="..\..\Folder\MyDll.Service.Context\bin\Release\MyDll.Service.Context.dll" target="lib\net452"/>
<file src="..\..\Folder\MyDll.Service\bin\Release\MyDll.Service.dll" target="lib\net452"/>
</files>
</package>
Unfortunately, all that did was cause my MyDll.Service.dll dll to show up twice in my package, once in the build folder and once in the lib folder. However, upon build the dll was still not in the folder.

Categories