target framework considerations with nuget packages? - c#

I'm fairly new to the process of creating NuGet packages. I recently created a NuGet package via NuGetPackageExplorer. The "Package Metadata" view has a "Framework Assembly References" section with a value of "Microsoft.CSharp (Any,Verion=0.0)." This is what the nuspec file looks like:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>My.Cool.NuGet.Package</id>
<version>1.0.2</version>
<title></title>
<authors>John Smith</authors>
<owners>John Smith</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>My cool NuGet package</description>
<frameworkAssemblies>
<frameworkAssembly assemblyName="Microsoft.CSharp" />
</frameworkAssemblies>
</metadata>
</package>
Can you please explain relationships, dependencies and constraints for the following dimensions:
Target Framework version of the source .NET project for the NuGet package
frameworkAssemblies section of the nuspec file
Target Framework version of the project which installs the NuGet package
The frameworkAssembly value in the nuspec above is displayed as follows in the NuGetPackageExplorer:
Assembly name: Microsoft.CSharp
Supported frameworks: Any,Version=v0.0
Does this mean that the NuGet package is intended to be .NET framework version agnostic? Are there any scenarios where I would want to explicitly state a specific version(s) in this section? The reason I'm asking is that I installed a NuGet package in an MVC project yesterday and I was experiencing some weird behavior. Specifically:
The NuGet package showed as installed and displayed in the References list
I was able to add a using directive to the namespace of the NuGet package
However, when I attempted to run the app, the compiler displayed an error of "type of namespace not found" for these using directives. But then the compiler errors disappeared but the app wouldn't run b/c of the previous compiler errors. After I fiddled with the version settings with the MVC project and NuGet package source project, I was able to get around this error. So now I'm trying to get an understanding of the finer details of what I need to consider and configure in regards to target frameworks.

The TargetFamework of the source project for the NuGet package should be the lowest framework version you need by projects that will install it. For example if you know you will have projects in the 4.5 and 4.6 framework you make the source for the package 4.5. You can also put multiple builds for multiple frameworks inside a package. Here is the documentation about that.
The TargetFramework for the projects installing the package should be greater or equal that the version of the package. Since higher versions of the framework are compatible with lower versions. It should not allow you to install a package that is not supporting the framework you are using in the project.
The frameworkAssemblies sections just defines which framework assemblies a package is using so the references are automatically added. Check the documentation for more detailed info.

Related

Installing a netstandard2.0 Nuget Package inside a different netstandard2.0 library NU1202

I'm currently struggling with something that seems like it's simple, but I can't track down anyone with a similar issue.
I'm converting some libraries to netStandard and one depends on another. We'll call them A and B.
A is compiling fine as a netStandard2.0 library, built with the 3.1 SDK according to dotnet --version in the directory. The nupkg is built in the Release folder and I move it to a local package source to test on my box.
B is a netStandard2.0 class library as well. It requires A, but navigating to my nupkg for A inside of NuGet Package Manager for B and clicking install generates a curious error.
NU1202 A is not compatible with netStandard2.0, Package A supports: netcoreapp2.1
A is a netStandard library.
B is a netStandard library.
When I look at the A.csproj file in the tag I'm seeing:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Description>The initial .net standard 2.0 offering of A</Description>
</PropertyGroup>
</Project>
So it seems to be targeting for a netStandard2.0 (which includes netFramework 4.6.1 to netCore 2.2?)
Am I missing something simple?
After googling around with nu1202 and netStandard2.0 - which mostly came up with a scenario of A being a library and B being an application, not a B being a library like my situation - I present:
Things I've Tried Based on Dissimilar Problems
Confirm the dotnet --version of each of the A / B projects, both at 3.1.402
Confirmed my Nuget Package Mangaer version is fairly recent / up to date: 5.7.0
Attempted to use the Package Manager Console to the exact same result.
Cleaned and Rebuilt / Packed the A.csproj
Tried including the A.nuspec file in the Package Source folder with A.nupkg
Pulled the A.csproj manually into the project to confirm it could be added as a Project Reference which worked, but isn't how I want to solve this problem.
I've maybe tried more but at this point, maybe the question I should be asking is: Is it possible to reference netStandard libraries inside of other netStandard libraries?
What am I missing?
I believe, in the end, that this might be an issue with the Pack/Build (with Generate Package on Build) functionality in VS.
I am able to manually create the package of the A library inside of Nuget Package Explorer, that package will import into B just fine.
I followed this resource, but was never able to build the package using Visual Studio, which makes it difficult to modify the version of Nuget Package Manger nowadays since it's bundled in. I'm at version 5.7, it may be that 5.6 would work as that's listed as the latest Stable release on google, but either way - for now, I believe I'll just manually make my packages instead of trying to auto-generate them.
If anyone has a better solution or thoughts about how to troubleshoot this, I am all ears.
EDIT
It turns out, the auto package build feature DOES work.
What happened in the end: I commandeered some old .net Core library titles, to downshift them to .net Standard instead of keeping 2 parallel copies.
There was already a .net core version of A.1.0.0.nupkg and a B.1.0.1.nupkg, but in a different nuget package source.
When I build a NEW .net Standard A.1.0.0.nupkg and put it in a local source, somehow even when pointing to that local source, nuget tried to install the .net core from ... i guess a cached copy of the production nuget package source (I cleared caches like 50 times so I don't know how nuget is getting these wires crossed).
Easily replicatable by making a version .net Standard A.1.0.1.nupkg, it imports fine because there was no .net core A.1.0.1.nupkg. You can then rename that package and reversion it in Nuget Package Explorer, but not change the contents, and it will fail. This was confirmed when I had to stair step my versioning of the .net Standard version of B.nupkg from 1.0.0 to 1.0.2 thus going further than the .net Core version of B.nupkg.
So in the end, the auto package functionality isn't broken (thankfully). The Nuget Package Explorer manual creation fixed my problem because I ticked up the version when I manually made it.
I would never have expected the production library package source to interfere with a local package folder...

How to resolve the error from changing target version of a project in a solution?

In the project I am currently working on, there are several projects in the solution. I had to change the target version of a particular project, which is responsible for handling particular APIs of the project, for installing certain Nuget Packages.
Now there are some .dll not found errors coming when I try to run the project.
How can I resolve this issue?
My project is based on .net framework and I am using Visual Studio 2017.
My actual Target version was .NET Framwork 4.5.1.
I had to change it to 4.6.1 since the package I was trying to install IBM.Watson.NaturalLanguageUnderstanding.v1 -Version 4.2.1 package.
Errors are like this:
Metadata file 'location\ProjectName.dll' could not be found.
My actual Target version was .NET Framwork 4.5.1. I had to change it
to 4.6.1 since the package I was trying to install
IBM.Watson.NaturalLanguageUnderstanding.v1 -Version 4.2.1 package.
I recreated the problem by attempting to install the nuget on a new console app targeting .netframework 4.6.1 and it failed
This is where problem lies, IBM Watson NaturalLanguageUnderstanding is compatible with .NETStandard 2.0 Specification which means you would need to target 4.6.1 (*2) ideally, but here is the catch (as explained here MSDN)
2 ways to solve this
Target .NetFramework 4.7.1 as recommended by the MSDN above OR
If you want to use 4.6.1 then you would need to add this to your .CSPROJ file
<PropertyGroup>
.
.
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
To resolve the issues, change the target frameworks of the projects that are dependent on the project for which the target framework was changed. In most cases, there won't be much problem since Microsoft gives backward compatibility. There might be some problems with third-party NuGet packages. Also, some reference errors might come when deployed.

Unable to consolidate NuGet package transitive dependency versions in two NET Standard projects

Adding EF Core to a NET Standard project introduces transitive dependency versions incompatible with NuGet packages in other projects
I have a solution with multiple .NET Standard 2.0 projects.
One Project A uses the Google.Protobuf (3.11.2) NuGet package, that depends on
System.Memory (4.5.3)
System.Buffers (4.4.0)
System.Numerics.Vectors (4.4.0)
System.Runtime.CompilerServices.Unsafe (4.5.2)
A few other projects also depend on System.Memory and all use the same dependency versions.
Another Project B uses Microsoft.EntityFrameworkCore (3.1.0) NuGet package that depends on
System.Memory (4.5.3)
System.Buffers (4.5.0)
System.Numerics.Vectors (4.5.0)
System.Runtime.CompilerServices.Unsafe (4.7.0)
Even though the System.Memory version is (4.5.3) in both cases, it depends on System.Buffers, System.Numerics.Vectors and System.Runtime.CompilerServices.Unsafe and their versions differ.
When I run the application that uses these projects (a Microsoft Prism WPF .NET Framework 4.8 app that uses Unity IoC) UnityContainer throws the following exception:
System.IO.FileLoadException: 'Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.
After searching for a solution I added this to my NuGet.Config:
<config>
<add key="DependencyVersion" value="Highest" />
</config>
In both, %appdata%\Nuget and in the root folder of the .sln file.
I also deleted the %userprofile%\.nuget\packages folder.
Then I removed the NuGet packages from the projects and added them back again, but their dependecies come with the same versions as before.
If I navigate to "Manage NuGet Packages for Solution..." in Visual Studio and choose "Consolidate" it just says "No packages found"
I managed to reproduce the problem.
I created two new .net standard 2.0 project class libraries.
On the first I added EF Core.
On the second I added Google protobuf.
Both same versions as you mention.
For EF core I created a new class that just inherits from DbContext.
For Protobuf I just created an empty class as I am not familiar on how to use it.
I was still able to replicate the problem though.
Then I created a console app .net framework 4.7.2 referencing the above two projects.
I instantiated the two classes in the Console App and got error System.IO.FileLoadException: 'Could not load file or assembly...
How I resolved it
I went to all three projects and added this line to the csproj.
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
to the Property Group.
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
After that I built and ran again and no error appeared.
Please let me know your results.
Even if my solution does not work for you, I believe it is good practice to have it.
To quote Oren.
"Using .NET Standard requires you to use PackageReference to eliminate the pain of “lots of packages” as well as properly handle transitive dependencies. While you may be able to use .NET Standard without PackageReference, I wouldn’t recommend it."
Also Hanselman mentions:
"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.""
Here are my sources.
https://www.hanselman.com/blog/ReferencingNETStandardAssembliesFromBothNETCoreAndNETFramework.aspx
https://oren.codes/2017/04/23/using-xamarin-forms-with-net-standard-vs-2017-edition/
Updated according to Sommen's extra info from the github issues
Kudos to Sommen for providing this extra info. Also Kudos to Immo Landwerth for providing this Info at GitHub.
I will provide as is the Workarounds that already exist in the Github page just for complecity as advised by the OP jinjinov.
Taken from GitHub Issues
Workarounds
Regular .NET Framework projects
Enable automatic binding redirects in the root .NET Framework application
Make sure your root application project doesn't use packages.config but uses PackageReference for NuGet packages:
If you currently don't have packages.config, simply add
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>.
If you currently do have a packages.config, convert the contents to package references in the project file. The syntax is like this:
<PackageReference Include="package-id" Version="package-version" />
ASP.NET web applications and web sites
Web applications and web sites don't support automatic binding redirect generation. In order to resolve binding conflicts, you need to double click the warning in the error list and Visual Studio will add them to your web.config file
In web application projects, you should enable PackageReference like mentioned above. In web sites, you cannot use PackageReference as there is no project file. In that case, you need to install all NuGet packages into your web site that any of the direct or indirect project references depend on.
Unit test projects
By default, binding redirects aren't added to class library projects. This is problematic for unit testing projects as they are essentially like apps. So in addition to what's outlined in automatic binding redirects you also need to specify GenerateBindingRedirectsOutputType:
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
There is also a discussion section that provides more information -> GitHub discussion
Yeah, welcome to the struggle.
Like PanosKarajohn pointed out using packagereference instead of packages.config helps with this. Unfortunately, that is Vs2017 and up and for some of us that is not yet in sight.
The problem is actually explained pretty much here:
https://github.com/dotnet/announcements/issues/31
You need to use binding redirects to redirect all the version numbers to the highest on you got and then pray that everything plays nice with each other.
I use the Microsoft.aspnetcore.signalR package in a .net 4.6.1 project and you have the same issues.

Why nuget from VSTS nuget feed wants to install the same package multiple times and throwing error?

I have a REST Api implemented using Durable Function App in Azure, which uses netstandard2.0, and I have other class libraries in this solution also using netstandard2.0. One of them is contracts projects.
There is another solution where the UAT tests placed for this solution. The reason for this is that Specflow is still not available for .Net Core, it is available for .Net Framework only. Being able to test the Api I need the contracts for the Api. That is the reason I need to include the REST Api solution Contracts project (this one is netstandard2.0). This dependency is managed by nuget.
When I would like to install the Contracts package (using netstandard2.0) in Specflow project (which uses .Net Framework 4.7.1) I get the error below.
What I tried:
I restarted Visual Studio a few times because I experienced that sometimes it gets crazy when .Net Core or .Net Standard projects are in use. Restarting did not help.
I opened the project from JetBrains Rider, but it did not see the netstandard2.0 nuget package in the repository. I believe it is due to that the project uses .Net Framework 4.7.1 and not Net Standard 2.0
I saw the error Cannot create "C:\...\REST.Api.dll" because a file or directory with the same name already exists.. So, I deleted all packages under the solution packages directory. I also deleted cache in Visual Studio. But, the next time I started Visual Studio and tried to install package the same error occurred again.
I also tried to install package using console on my machine (nuget.exe install ...). The error is the same.
How it is possible to resolve this issue? I read that from .Net Framework 4.6 and above and .Net Core it is possible to reference .Net Standard libraries.
Attempting to gather dependency information for package 'REST.Api.1.0.0-20180305-154726' with respect to project 'MasterData.Features.HttpClient', targeting '.NETFramework,Version=v4.7.1'
Gathering dependency information took 861.8 ms
Attempting to resolve dependencies for package 'REST.Api.1.0.0-20180305-154726' with DependencyBehavior 'Lowest'
Resolving dependency information took 0 ms
Resolving actions to install package 'REST.Api.1.0.0-20180305-154726'
Resolved actions to install package 'REST.Api.1.0.0-20180305-154726'
GET https://xyzrepository.visualstudio.com/_packaging/689a2aa0-1e6a-4f39-8389-250b4ad44db8/nuget/v3/flat2/REST.api/1.0.0-20180305-154726/REST.api.1.0.0-20180305-154726.nupkg
Retrieving package 'REST.Api 1.0.0-20180305-154726' from 'Sayusi Ando's Digital Library Packages'.
OK https://xyzrepository.visualstudio.com/_packaging/689a2aa0-1e6a-4f39-8389-250b4ad44db8/nuget/v3/flat2/REST.api/1.0.0-20180305-154726/REST.api.1.0.0-20180305-154726.nupkg 2343ms
Installing REST.Api 1.0.0-20180305-154726.
Error downloading 'REST.Api.1.0.0-20180305-154726' from 'https://xyzrepository.visualstudio.com/_packaging/689a2aa0-1e6a-4f39-8389-250b4ad44db8/nuget/v3/flat2/REST.api/1.0.0-20180305-154726/REST.api.1.0.0-20180305-154726.nupkg'.
Cannot create "C:\Users\username\.nuget\packages\REST.api\1.0.0-20180305-154726\lib\netstandard2.0\REST.Api.dll" because a file or directory with the same name already exists.
GET https://xyzrepository.visualstudio.com/_packaging/689a2aa0-1e6a-4f39-8389-250b4ad44db8/nuget/v3/flat2/REST.api/1.0.0-20180305-154726/REST.api.1.0.0-20180305-154726.nupkg
OK https://xyzrepository.visualstudio.com/_packaging/689a2aa0-1e6a-4f39-8389-250b4ad44db8/nuget/v3/flat2/REST.api/1.0.0-20180305-154726/REST.api.1.0.0-20180305-154726.nupkg 462ms
Installing REST.Api 1.0.0-20180305-154726.
Error downloading 'REST.Api.1.0.0-20180305-154726' from 'https://xyzrepository.visualstudio.com/_packaging/689a2aa0-1e6a-4f39-8389-250b4ad44db8/nuget/v3/flat2/REST.api/1.0.0-20180305-154726/REST.api.1.0.0-20180305-154726.nupkg'.
Cannot create "C:\Users\username\.nuget\packages\REST.api\1.0.0-20180305-154726\lib\netstandard2.0\REST.Api.dll" because a file or directory with the same name already exists.
GET https://xyzrepository.visualstudio.com/_packaging/689a2aa0-1e6a-4f39-8389-250b4ad44db8/nuget/v3/flat2/REST.api/1.0.0-20180305-154726/REST.api.1.0.0-20180305-154726.nupkg
OK https://xyzrepository.visualstudio.com/_packaging/689a2aa0-1e6a-4f39-8389-250b4ad44db8/nuget/v3/flat2/REST.api/1.0.0-20180305-154726/REST.api.1.0.0-20180305-154726.nupkg 464ms
Installing REST.Api 1.0.0-20180305-154726.
Install failed. Rolling back...
Package 'REST.Api.1.0.0-20180305-154726' does not exist in project 'MasterData.Features.HttpClient'
Package 'REST.Api.1.0.0-20180305-154726' does not exist in folder 'C:\VSTS\REST.QA.Features\src\packages'
Executing nuget actions took 3.51 sec
Error downloading 'REST.Api.1.0.0-20180305-154726' from 'https://xyzrepository.visualstudio.com/_packaging/689a2aa0-1e6a-4f39-8389-250b4ad44db8/nuget/v3/flat2/REST.api/1.0.0-20180305-154726/REST.api.1.0.0-20180305-154726.nupkg'.
Cannot create "C:\Users\username\.nuget\packages\REST.api\1.0.0-20180305-154726\lib\netstandard2.0\REST.Api.dll" because a file or directory with the same name already exists.
Time Elapsed: 00:00:05.5462783
The root of the problem is that the target properties conflicted with another filename. (names are shortened)
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<!-- package stuff -->
<dependencies>
<group targetFramework=".NETStandard2.0" />
</dependencies>
</metadata>
<files>
<file src="..." target="lib\netstandard2.0\Contracts.dll" />
<file src="..." target="lib\netstandard2.0\Contracts.dll" />
<file src="..." target="lib\netstandard2.0\Contracts.dll" />
</files>
</package>

nuget pack with -IncludeReferencedProjects flag don't work when NET Framework project has project reference to netstandard project

I have 2 libraries:
first library(First.csproj) - netstandard1.3
second library(Second.csproj) - .Net framework 4.6.1
Second.csproj has project reference to First.csproj.
Compilation into VS2017 working without problems.
After that i want to create nuget package for Second.csproj with dependency to First.csproj, but command
nuget pack Second.csproj -IncludeReferencedProjects
Failed with error
Error occurred when processing file 'E:\blabla\First.csproj': Unable to find 'bin\Release\First\bin\Release\'. Make sure the project has been built.
Unable to find 'bin\Release\First\bin\Release\'. Make sure the project has been built.
My nuget version is latest: NuGet Version: 4.4.1.4656
How can i correctly pack my .NET Framework 4.6.1 project with adding dependency to netstandard library?
It's a known bug of nuget: https://github.com/NuGet/Home/issues/4054.
Ugly workaround:
1) Manually add dependency on package of First.csproj into .nuspec file of Second.csproj
<dependencies>
<dependency id="First" version="actual version of First here" />
</dependencies>
2) Use nuget pack without flag -IncludeReferencedProjects

Categories

Resources