Custom Nuget package shows missing dependency error - c#

I have two class libraries in a single solution (.NET Core). One of them (cl1) is a main library and it depends on another library (cl2). I have added a .nuspec file with the required metadata only (no dependencies, no files) for the cl1 project in the project folder (same location of .csproj file) and I have set GeneratePackageOnBuild propery to true.
Whenever I am building the class library (cl1), the .nupkg is created automatically in the debug/release folder.
When I check the generated .nupkg file, I am see two strange things:
The generated .nuspec file is different than what I have added in the project folder
cl2 is mentioned as a dependency in the newely generated .nuspec file, but the DLL for cl2 is not included in the lib folder of the .nupkg. So, whenever I consume this package in another solution, I am getting the error No packages exist with this id in source(s) for the cl2.
I have surfed in internet, but was not able to find a proper solution for the above error.

And I have added a .nuspec file [...] in the project folder(same location of .csproj file)
You have to specify the path to your own NuSpec file in the .csproj using the NuspecFile tag, otherwise it will be ignored and the package will be created with the metadata from the .csproj file instead, see reference. You need to use either a relative or an absolute path to the file, for example:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<NuspecFile>cl1.nuspec</NuspecFile>
</PropertyGroup>
</Project>
The generated .nuspec file is different than what I have added in the project folder
As already stated, your NuSpec file is probably not included. However, even if it is, there can be differences, because some information, e.g. source file locations are unnecessary and the target locations are in most cases given by the internal package file structure itself, so it is not there because it is redundant.
cl2 is mentioned as a dependency in the newely generated .nuspec file, but the dll for the cl2 is not included in the lib folder of the .nupkg. So, whenever I consume this nupkg in other solution, I am getting error " No packages exist with this id in source(s)" for the cl2.
Dependencies are meant for packages. So when NuGet restores the package it searches for other packages that this package depends on, here cl2, but there is none, hence the error. When packing a project, referenced projects are not included in the package. That is an open issue and there are workarounds that you can try.
The most reliable, but inconvenient solutions are to avoid the issue at all.
Only use a single project, everything will be included in the package
Pack each project on its own and use the generated package instead of the referenced project

Related

Copy a file to other project using Nuget package

I am trying to get my head around how Nuget works when creating packages and must admit that I cannot grasp it.
To generalize my task, it is to include a file in the Nuget package, create that Nuget package and when installed as a dependency in other project, the file is shown there in the project structure or somewhere to be manipulated with.
This file is a central .DotSettings file which would then propagate to all the C# repositories and solutions.
Where I am now
I have a .dll project, I have my content folder where the file is and I specify that within the .csproj file as such:
<ItemGroup>
<Content Pack="True"
PackagePath="\"
Include="content\test.DotSettings" />
However, when this is Nuget packed and this dependency is installed in another project, I cannot see this file in the project/dependencies/packages folder, where I would like it to be (and I suppose it should be there, right?)
The workaround I have now is that I reference this file from within the users/nuget/packages folder, however, I do not fancy this solution that much.
So, the main question:
Is there a way to copy the file so that when the dep is installed, the file is shown at the top level project folder structure? if so, what am I missing?
misc questions:
As I understood it, I can write my own .nuspec file and specify it there somehow, but when I did that, at build it always overrides it with its own autogenerated .nuspec file. Is this a wrong way to take at all and should I not create my own .nuspec?
What about the .target and .props file, what is that for and do I need to bother with those in my task or not at all? From what I understood, I should be good with my .csproj file and be able to define it all within it.
TIA!

Add props file properties/variables to csproj hint path

I have added .props file and included it in .nuspec file.
In my .props file i have added new properties/elements in PropertyGroup.
After installing my nuget package, .props file is importing successfully in .csproj file. But how can I include/add props files properties/variables in HintPath (not manually).
Using HintPath & .nuspec for your nugets is an indicator of legacy approach, consider PackageReference & SDK style csproj instead, there is no hint path at all, they are all automatic.
Legacy of Hint Path
Hint path usually used as an item metadata for Reference items for nuget-installed assemblies. Legacy project format been developed when nuget was an external tool (now it is part of .Net SDK). At that time the approach was to have packages.config (you no longer need it) with the list of nugets installed to the project, and while package been installed it have to appear to the rest of .net tools as a regular sideloaded set of assemblies, this is why DLL files are been restored to "packages" folder (this no longer happens), and Reference items are been added to the project with a HintPath having relative path to this "packages" folder. This includes whole graph of references, so if PackageA uses PackageB then both are deployed to "packages" folder and both produces Reference item on all libraries from every package. This way legacy tools used to bring package management to existing ecosystem. For a new PacakgeReference approach you only have to specify top-level package, all transient references will be processed automatically on a restore & build time.
Custom Targets
Since you are mentioning you have props file in your nuspec, let me clarify how now it can be achievend in SDK style csproj in a package that your are publishing (there is no nuspec, all nuspec data is now inside csproj):
<ItemGroup>
<None Include="your_custom.props_or_targets">
<Pack>true</Pack>
<PackagePath>build</PackagePath>
</None>
</ItemGroup>
So, destination path is specified in PackagePath item metadata and it should be build to denote that this is auto-installable targets.
Now in legacy approach when installing package like this, a consumer project automatically have "Import" node to explicitly bring this targets to the project. Now in new SDK approach, if you import package like this with PackageReference, you will not find Import node - it is actually implicitly assumed, so if package under question have targets & props in build folder - all of them will be automatically imported in a build time (not in design time).
PackageReference
<ItemGroup>
<PackageReference Include="YourPackage" Version="3.6.0" />
</ItemGroup>
So if you consume project like this, this is enough to consume Properties that you bring with your custom props inside this package. Feel free to use them as usual an hopefully you no longer need HintPath at all.

Documentation disappears in NuGet package

I wrote a class library in C# that I need to push to a private NuGet server (v3.4.1.0). I decorated my classes and methods with XML documentation comments.
XML documentation file option is checked on the Build tab of the project properties panel, the project builds successfully and the xml file gets generated on the project's root folder with the same name as the assembly.
In the .csproj file the related section looks like this:
<PropertyGroup>
<DocumentationFile>absolutePathTo\assemblyName.xml</DocumentationFile>
</PropertyGroup>
IntelliSense (VS2019 16.9.0) recognises the documentation and shows it properly even in other projects under the same solution.
When I generate the NuGet package it gets created in the project's bin\Debug folder. If I open it as a zip archive the DLL and the documentation XML can be found in the lib\netstandard2.1 folder having matching names.
Once I install this package to another project from the private NuGet server it works properly but loses the complete documentation. IntelliSense does not show my comments anymore and the assembly metadata seems not to have it either.
Could anyone support me on this one?
That is normal. For xml document, it is special under new-sdk style projects. The xml document could only be copied into the non-sdk net framework projects but new-sdk net core projects cannot. More similar to this issue I handled before.
So you should try these steps additionally to get what you want:
1) enter these node under csproj file of your nuget project.
<ItemGroup>
<None Include="xxx\absolutePathTo\assemblyName.xml"(the path of the xml file under your project folder) Pack="true">
<PackageCopyToOutput>true</PackageCopyToOutput>
</None>
</ItemGroup>
2) after that, re-pack your nuget project and before you install the new version, please clean nuget caches first or just delete all files under C:\Users\xxx\.nuget\packages
Personally, I let Visual Studio handle things for me.
If you right-click in the project, and choose Properties,
In the Build -> Output area, you should see a checkbox under Documentation file labelled Generate a file containing API documentation..
When you check this, a new option appears underneath: XML documentation file path. But the file selector is labelled Optional path for the API documentation file. Leave blank to use the default location..
FYI: The default location is alongside your EXE / DLL that is generated when you build your project.
When you next build your code (for anyone else reading, I assume you've got the Generate NuGet package on build in the Package area checked too) it will also package up the XML documentation into the NuGet package generated.
From the perspective of users of this new package, Visual Studio will pick up on the XML Documentation inside.

Create multi-target nuget package from several csproj contained in different folders from nuspec file

I am trying to create a nuget package for a library which exists in 2 versions, each of them targeting two different .NET versions.
Here is my folder structure:
As you can see my nuspec file is one directory above my csproj (which are in the /net452 and /netcoreapp2.0 folders).
I am using the following command line to build my nuget package:
nuget pack .\my.nuspec -properties Configuration=Release -Build
The issue is that the build can not be achieved because the csproj files are not in the same folder as the nuspec file.
Please note that the packaging works fine when both projects have been priorly manually built.
I'm very new to this process and I'm not sure what I should do in that scenario, is there a simple way to reference the 2 csproj from the nuspec or - assuming I want to keep this folder structure - would I need to make a script that builds the projects first and then invoke nuget pack?
EDIT: To clarify my issue, I do have two different csproj files, contained respectively in /net452 and /netcoreapp2.0, and they compile the source code in their respective directory to produce two different dll. These two dll are then referenced in my nuspec file in order to offer my package in net452 or netcoreapp2.0 with the following syntax:
<files>
<file src="lib\**" target="lib" />
</files>
Note: after I manually compiled my two projects, the directory looks like this (note the lib folder that contains a net452 and netcoreapp2.0 folder with the appropriate version of my dll).
Not sure if understood correctly - you have one library and want to build it in two versions (net452 and netcore).
Did you try adding following items to *.csproj?
<PropertyGroup>
<TargetFrameworks>net45;netcoreapp2.0</TargetFrameworks>
</PropertyGroup>
Then you can have on project with two outputs from build

Copy all of the required dlls to folder

I have a MonoAndroid10 project and it has a lot of dependencies(NuGet packages too). I would like to be able to copy all of the DLL dependencies to the output folder.
Normally in a .Net Standard 2.0 project the following
<PropertyGroup>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
would make that possible. But in the MonoAndroid project, nothing happens.
If what I posted above doesn't work for a MonoAndroid project, how could I copy everything that I need in some folder, preferably in a post-build action?
I'm trying to do this because after copying all of the required DLLs in one folder I can merge them together with ILRepack.
I've come across this today, solved by adding
<CopyNuGetImplementations>true</CopyNuGetImplementations>
to android project .csproj file (under the desired PropertyGroup section).
Note: there is no need to set CopyLocalLockFileAssemblies to ture neither in android project nor in any of the dependencies.

Categories