Resolving nuget package references - c#

I am writing an app which needs to load nuget packages dynamically (it uses Roslyn to scan for documentation, type information, etc).
I have a situation where I want to load the following package (info derived from a csproj file):
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>J4JSoftware.Logging</AssemblyName>
<RootNamespace>J4JSoftware.Logging</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
</ItemGroup>
The challenge is that my system's nuget cache does not have an assembly/DLL for a netstandard2.0 version of Serilog.Sinks.Console 3.1.1 (I don't think one exists online, either). All it has is one for netstandard1.3.
Yet the app that I'm scanning (i.e., the one with the requirement for Serilog.Sinks.Console 3.1.1 netstandard2.0) works perfectly fine. So the package requirement is being resolved, I presume, to the netstandard1.3 version...even though the project is netstandard2.0.
Questions:
what's the best place for documentation on how nuget packages are resolved at runtime? Perhaps I could duplicate the resolving function in my scanning app.
better yet, is there a library that handles the resolution automagically? Perhaps something that's part of nuget itself? I studied the nuget github project but didn't see such a thing, but I don't pretend to be a nuget expert.

I would do something like: nuget update or nuget list and interact from C# etc with the console. That way you are sort of getting a library like behavior but not baking your own code that may break across nuget versions.
NetStandard 1.3 is likely usable for Netstandard 2.0 as mentioned here (but not the other way around).
Nuget versioning would declare that you want say Netstandard 2.0 and the package you are using might say it supports NetStandard 1.3+ (which includes Netstandard 2.0 implicitly). Nuget will select the highest one provided that suites your needs, in this case probably 1.3 as you indicated. Details are here on how nuget selects dependencies. I assume that this is the same way in how it determines runtime folders.

Related

Is NuGet metapackage reserved to .net core only?

In the .NET doc, I see a lot of explanations around nuget metapackages, bu all the samples are with .NET Core. Is it possible to create metapackage for full .net framework assemblies and consume this with a .net framework app?
Will it be possible only with ProjectReference and not with packages.config?
Thanks!
A metapackage is just a package that doesn't contain any content/libraries of its own and has dependencies to all the other packages that it encompasses. This isn't something specific to NuGet, by the way, many package managers have the same concept and usually call them meta packages too.
About NuGet specifically, since NuGet has to deal with different target frameworks and asset selection, which many package managers don't have to worry about, it might be necessary to put some fake information in the nupkg to make it work properly. What I think I've seen before is to create an empty file named _._ in the lib\target framework folders that match the TFMs that the dependant packages use. For example, if you create a metapackage for packages that have libs for net45 and netstandard2.0, then you'd have two files in the nupkg, lib/net45/_._ and lib/netstandard2.0/_._, both are empty. However, I haven't tested this myself, so you should, but just in case a nupkg with only a nuspec and nothing else doesn't work, try this.
Since meta packages aren't otherwise special (they have the same package type as "regular" packages), they work just fine with both packages.config and PackageReference. Meta packages are perhaps most useful for PackageReference, because it supports transitive dependencies. In other words, the user adds the metapackage, their csproj gets one reference and is otherwise "clean". With packages.config, when they add the metapackage, all of the transitive dependencies will also get added to packages.config and csproj.

Could not load file or assembly When Net Framework reference a Net Standard Library

I am very new to netstandard and I just encountered exception when I want to run a debug mode a .Net Framework (console) which has reference to a netstandard library.
So I later figured out that the exception would be gone if I installed the System.IO.Ports from nuget onto the .Net Framework Project. But this library has already installed onto netstandard project.
So I highly doubt that if I need to install all the libraries which netstandard project required if I uses the netstandard project from another .net framework project.
I must be missing something, can anyone who is familiar with netstandard give me some insights about it.
your inputs are much appreciated !
Open up the .csproj file for the .Net Framework project that is hosting the .Net standard library and add this line within the first <PropertyGroup> like this to change the restore style:
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
Check out this article by Scott Hanselman about the cause of the issue and the fix.
From the article:
The "full" Framework projects are using the older .csproj format and by default, they use package.config to manage dependencies. The newer projects can reference Packages as first-class references. So we need to tell ALL projects in this solution to manage and restore their packages as "PackageReferences."
EDIT:
This fix worked perfectly for me on a new project. When I apply it to the csproj before I restore packages in that new project, nuget gets the correct references.
When applying this to an existing project, it doesn't work. The libraries that are referenced inside the .net standard class library are not pulled by nuget and therefore, it would still throw the same error.
To fix it try this:
Open the csproj. You will notice your library looking like that
<Reference Include="yournetstandardlibrary, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\yournetstandardlibrary\lib\netstandard2.0\.dll</HintPath>
</Reference>
Delete that reference
Add this reference instead
<ItemGroup>
<PackageReference Include="yournetstandardlibrary">
<Version>1.0.1</Version>
</PackageReference>
</ItemGroup>

Solution targeting .NET Core 2.1 builds with old System.ServiceModel.Primitives and System.Private.ServiceModel

I have a solution made up of projects targeting .NET Standard 2.0 and .NET Core 2.1.304. When built this solution utilizes old vulnerable versions of System.ServiceModel.Primitives and System.Private.ServiceModel (CVE-2018-0786).
I am probably missing something obvious about the configuration of the overall solution or one of the projects that is causing the utilization of the old versions, but everything I know to check looks correct:
Global.json
{
"sdk": {
"version": "2.1.302"
}
}
Example .NET Core Project File
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<Configurations>Debug;Dev;Qual;Release</Configurations>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
Example .NET Standard Project File
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Configurations>Debug;Dev;Qual;Release</Configurations>
</PropertyGroup>
I have ensured all NuGet packages are up to date. That said is it possible that one of my NuGet package references is causing a fallback to the old versions? What other configurations should I be checking?
Interestingly when I build a different, but similarly configured solution (from what I can tell) that solution produces a build using the newer non vulnerable versions.
You can use a tool such as dotnet-outdated to determine both your the versions of your dependencies and transitive dependencies in your project.
Install via dotnet tool install --global dotnet-outdated on the powershell command line
and run dotnet outdated -t -td 100 in your solution folder to see 100 levels of transitive dependencies.
Your output will look something like the following
ยป MyProject
[.NETCoreApp,Version=v2.1]
System.Private.ServiceModel [T] 4.4.0 -> 4.5.3
System.ServiceModel.Primitives [T] 4.4.0 -> 4.5.3
You can then use the above stated out of date dependencies to track down which project(s) in your solution needs to be further investigated.
From there eliminate dependencies that are known to be safe, as they appear in other projects that don't have a dependency on the bad library (regardless of version). At this point it may be a matter of using nuget.org and investigating each suspect dependency to see what version of sub-dependencies it uses.

Nuget Package without Package.Config?

I encountered a solution (.Net Full framework) Where there are no package.config in the solution and Feeds coming from In house Nuget servers.
Where list of packages are maintained, if not in Package.Config?
Where is the list of packages are maintained, if not in Package.Config?
First, you should make sure you have that solution have already installed the nuget package, once you install a package, NuGet will add Package.Config file to your project to record the dependency in either your project file or a packages.config file.
If you confirm that your solution has a nuget package installed, but there is no Package.Config file, your nuget package should use another management method: PackageReference
Edit your project, you will find following PackageReference list:
<ItemGroup>
<PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0" />
</ItemGroup>
See NuGet is now fully integrated into MSBuild for more details:
In the past, NuGet packages were managed in two different ways -
packages.config and project.json - each with their own sets of
advantages and limitations. With Visual Studio 2017 and .NET Core, we
have improved the NuGet package management experience by introducing
the PackageReference feature in MSBuild. PackageReference brings new
and improved capabilities such as deep MSBuild integration, improved
performance for everyday tasks such as install and restore,
multi-targeting and more.
The packages.config file could be somewhere else? In that case look in your msbuild project file (i.e. *.csproj, *.vbproj, *.vcxproj) and see where the references to that nuget assembly are coming from. Then look in that directory for the packages.config file. It might be more complicated than that, in which case, it's useful to do a global search for packages.config in your repo, to see where they reside (If they do exist at all).
This is a common practice: To have one project specify the nuget package, and all the other projects borrow it. As Jon said, this is really dependent on how the folks at your company and department set up your builds and dependencies.

Best practice to include console app in NuGet

I'm developing an open-source library which mainly consists of one class-library project targeting .NET Standard 2.0. On top of that, I've also implemented a console app which is the CLI to this library. The console project (for historic reasons) only targets .NET Framework 4.6.2.
Now I wonder what would be the best practice in order to make this console app available to the community. On the broadest level, I see two possibilities:
Ship the console app as a separate NuGet.
Ship the console app in the same NuGet as the class library because it's just a minor add-on and does not justify an own package.
Historically, I've been using the second approach but considering that the class library can be used in a multi-targeting scenario, I'm not sure anymore. Maybe it's cleaner to separate the console app in a NuGet of its own so that it's dependency on the full .NET framework is clear.
Either way I wonder where the console exe belongs to in the file structure of the NuGet. Historically, I've been putting it under tools\net462 but a comment about the tools folder on this page made me insecure:
Powershell scripts and programs accessible from the Package Manager Console
I'm not necessarily imagining someone using the CLI from the Package Manager Consoler. Rather it would be used as stand-alone exe somewhere is some shell.
Ther is a solution that seems to fit your needs. You can create a command line extension for the dotnet tools. Like dotnet ef you can create a dotnet myAwesomeTool command. The only thing that you need to do is the Following:
Create a console application and add the following code to your .csproj
<PackageId>Company.MyAwesomeTool</PackageId>
<AssemblyName>dotnet-myAwesomeTool</AssemblyName>
<PackageType>DotnetCliTool</PackageType>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
Build the solution and you will find a nuget package in your bin folder. This nuget package can be distributed and when you have installed it, you can run dotnet myAwesomeTool in the projects where the nuget is installed. Works like a charm for me =)
To install it on other projects, add this to the csproj:
<ItemGroup>
<PackageReference Include="company.MyAwesomeTool" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="company.MyAwesomeTool" Version="1.0.0" />
</ItemGroup>
For more infos:
https://blog.maartenballiauw.be/post/2017/04/10/extending-dotnet-cli-with-custom-tools.html
In general, NuGet is meant only for delivering class libraries (note the wording "if your library...").
Use Chocolatey instead for deploying command-line and GUI apps to Windows. It has a CLI that can be used to easily install and update applications. It is not NuGet, but uses a similar method to package and deploy the app.
There are also package managers to target other platforms:
apt-get (for Debian/Ubuntu/Mint)
Brew (for MacOS)
RPM (for Fedora/Red Hat)
NOTE: As Martin Ullrich pointed out in the comments, there is now a way to deploy build tool CLIs with NuGet, which is primarily meant for continuous integration deployment scenarios.
When time pass by, other solutions come available...
https://learn.microsoft.com/nl-nl/dotnet/core/tools/global-tools-how-to-create
<PackAsTool>true</PackAsTool>
<ToolCommandName>botsay</ToolCommandName>
<PackageOutputPath>./nupkg</PackageOutputPath>

Categories