How do I prevent installing nuget packages that aren't 100% .Net Core 2.0 compatible?
Asked Answered
P

3

10

I understand that .Net Core 2 has a compatibility shim that allows it use Nuget packages that don't specifically target .Net Core/Standard 2. This gives it access to 70% of Nuget. Great - nice feature.

How do I prevent installing nuget packages that aren't fully compatible with .Net Core 2/.Net Standard 2? Or warn me at point of installing that it is being used with the shim?

I created a new .Net Core 2.0 project installed EF 6.1.3 (which I knew didn't work) and nothing prevented me or warned that it didn't target .Net Standard <=2 at the point of install.

I am happy to "run with scissors" but I kind of feel I should be getting a warning before I install MVC5 and EF 6.1.3 into a .Net Core 2 application. I would really like to prevent junior devs from installing unsupported packages etc.

I guess further to Matt Ward answer - my main point is - can it be detected that something is actually 100% compatible at install or are we always just in the situation where we need to make determination ourselves that package works "well enough". I hoped that there was a technical mechanism that detected missing coverage API coverage and could tell us that the nuget package may not operate as it did before. So I guess MS say 70% compatibility - I want to fail if I try to install the 30%

Plentiful answered 16/8, 2017 at 11:31 Comment(0)
D
2

If you wan to be 100% sure, run the package against .NET Portability Analyzer and .NET Standard 2.0 profile.

It won't tell you if the API will be called or not (and is in no way an automatic process), just if the Assembly contains any API which is not .NET Standard 2.0 compatible.

However, you can also only run your application against the Analyzer, as the .NET Portability Analyzer should be able to follow any references made from the application and check these too.

Update

You can als build this into your build server pipeline, to get a more automatic guarantees.

The .NET Portability Analyzer Docs.

Visual Studio is not required for this, just download it from https://github.com/Microsoft/dotnet-apiport/releases and run

From the docs:

  • Type the following command to analyze the current directory: \...\ApiPort.exe analyze -f .
  • To analyze a specific list of .dll files, type the following command: \...\ApiPort.exe analyze -f first.dll -f second.dll -f third.dll

Old Answer (may be useful in conjcution with Matt's answer)

Untested, but give it a try:

<!-- old dotnet tooling/.NET Core 1.x -->
<PackageTargetFallback>netstandard2.0;portable-net45+win8</PackageTargetFallback>
<!-- new dotnet tooling/.NET Core 2.0 -->
<AssetTargetFallback>netstandard2.0;portable-net45+win8</AssetTargetFallback>

Typically you want to have it like

<!-- old dotnet tooling/.NET Core 1.x -->
<PackageTargetFallback>$(PackageTargetFallback);dotnet5.6;portable-net45+win8</PackageTargetFallback>
<!-- new dotnet tooling/.NET Core 2.0 -->
<AssetTargetFallback>$(AssetTargetFallback);dotnet5.6;portable-net45+win8</AssetTargetFallback>

Where $(PackageTargetFallback) will tell MSBuild to keep the old values and append the values after that to it. But since $(PackageTargetFallback) probably (can't look/dig deeper in right now) have the .NET Framework moniker there, you'll override it with your own values.

Additionally

Given that PackageTargetFallback is now deprecated, one should use AssetTargetFallback instead.

Darkle answered 16/8, 2017 at 11:35 Comment(8)
Entity Framework still seems to install quite happily with "Checking compatibility for EntityFramework 6.1.3 with .NETCoreApp,Version=v2.0." and then I get "All packages and projects are compatible with .NETCoreApp,Version=v2.0."Plentiful
Do you get any warnings while restoring? If yes, you can turn them into errors in project settingsDarkle
Nope no warnings. Clean new project - added EF 6.1.3 - just checks compat for 9 items (inc EF) and then just works (well until you use EF)Plentiful
I should be clear I get warnings on Nuget dependencies view if I look at them - I'm trying to prevent getting that farPlentiful
@Plentiful I just tried this with a project which targets .netCore 1.1 and it failed with a message saying that EF 6.3.1 is incompatible. Is there a difference between .netCore 1.1 & 2.0 or is there another option that is causing this?Coke
@ViktorSeifert .Net Core 2 supports a compatibility shim using to allow .Net Core projects to use assemblies not compiled for .Net standard as long as they support the appropriate APIs #44465437Plentiful
@Darkle just had discussion about analyser at work and we came to that conclusion. Given it is server based analysis be nice if it integrates into nuget install process to inform you or something similar. Hopefully people just update their packages to target standard 2.0.Plentiful
I just realized PackageTargetFallback is deprecated and one should use AssetTargetFallback instead, you could try that and give feedback if it worked better than PackageTargetFallback. I just noticed it because I tried to build my project via command line and the error happend, while Visual Studio didn't complain about it at allDarkle
Q
5

Installing Entity Framework 6.1.3 into a .NET Core 2.0 project there is a NU1701 warning in the Errors window about Entity Framework 6.1.3 being restored using .NET Framework 4.6.1 and that it may not be fully compatible.

You could turn the NU1701 warning into an error in the project so you could not install any NuGet package that does not explicitly support .NET Core 2.0. This can be done by adding the WarningAsErrors property to the project.

<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>netcoreapp2.0</TargetFramework>
  <WarningsAsErrors>NU1701</WarningsAsErrors>
</PropertyGroup>

Then if you try to install Entity Framework 6.1.3 the restore will fail, the changes will be rolled back, and the NuGet package will not be installed.

You can also set the DisableImplicitAssetTargetFallback property to true which will prevent .NET 4.6.1 being added to the AssetTargetFallback property which is used when checking NuGet package compatibility with .NET Core 2.0 projects.

<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>netcoreapp2.0</TargetFramework>
  <DisableImplicitAssetTargetFallback>true</DisableImplicitAssetTargetFallback>
</PropertyGroup>
Quod answered 16/8, 2017 at 14:15 Comment(6)
So if all the APIs that Entity Framework needed were present does NU1701 warning still occur? Or is it really saying this doesn't target .Net Standard X? To me it looks like the warning is just a generic message I would get that if I targetted any non .NetCoreApp? So guess what I am saying is - can I detect that something is 100% compatible and allow that but not allow stuff that isn't 100% compatible? Or are we left to our own devices to decide that something is compatible and there is no technical solution that says "yes" this supports all the APIs we need?Plentiful
It is saying that the EF NuGet package does not have any assemblies that are compatible with .NET Standard 2.0 or .NET Core App 2.0 and is assuming that the .NET Framework assembly provided by the NuGet package is compatible. The NuGet check is not comprehensive - it does not look at the assembly and check all the APIs it uses to see if it is compatible. There are probably tools that can do some sort of check like this but nothing built-in to NuGet or Visual Studio as far as I am aware.Quod
Making the NU1701 warning an error will block all NuGet packages that do not explicitly support .NET Core 2.0 but may be OK to be used. You would need some other tool to work out if they are completely compatible. I believe a good proportion of the most used NuGet packages are - there was some figure announced by Microsoft about this.Quod
Apparently 70% of all NuGet packages are compatible - blogs.msdn.microsoft.com/dotnet/2017/08/14/…Quod
Ok - so to my mind this is just a bit scary. I appreciate that package is tested via my code base Unit/Integration test and I can show that it works for scenarios I require How do know that under certain scenarios a package doesn't call an unsupported API etc and then just fails on Core at runtime? I just assumed there was going to be a bit more intelligence to the whole process and nuget/code inspection could tell me that MS felt that all the required APIs were present and assuming no bugs with implementation it should just workPlentiful
@GraemeMiller: If you wan to be 100% sure, run the package against .NET Portability Analyzer and .NET Standard 2.0 profile. It won't tell you if the api will be called or not, just if the Assembly contains any API which is not .NET Standard 2.0 compatibleDarkle
D
2

If you wan to be 100% sure, run the package against .NET Portability Analyzer and .NET Standard 2.0 profile.

It won't tell you if the API will be called or not (and is in no way an automatic process), just if the Assembly contains any API which is not .NET Standard 2.0 compatible.

However, you can also only run your application against the Analyzer, as the .NET Portability Analyzer should be able to follow any references made from the application and check these too.

Update

You can als build this into your build server pipeline, to get a more automatic guarantees.

The .NET Portability Analyzer Docs.

Visual Studio is not required for this, just download it from https://github.com/Microsoft/dotnet-apiport/releases and run

From the docs:

  • Type the following command to analyze the current directory: \...\ApiPort.exe analyze -f .
  • To analyze a specific list of .dll files, type the following command: \...\ApiPort.exe analyze -f first.dll -f second.dll -f third.dll

Old Answer (may be useful in conjcution with Matt's answer)

Untested, but give it a try:

<!-- old dotnet tooling/.NET Core 1.x -->
<PackageTargetFallback>netstandard2.0;portable-net45+win8</PackageTargetFallback>
<!-- new dotnet tooling/.NET Core 2.0 -->
<AssetTargetFallback>netstandard2.0;portable-net45+win8</AssetTargetFallback>

Typically you want to have it like

<!-- old dotnet tooling/.NET Core 1.x -->
<PackageTargetFallback>$(PackageTargetFallback);dotnet5.6;portable-net45+win8</PackageTargetFallback>
<!-- new dotnet tooling/.NET Core 2.0 -->
<AssetTargetFallback>$(AssetTargetFallback);dotnet5.6;portable-net45+win8</AssetTargetFallback>

Where $(PackageTargetFallback) will tell MSBuild to keep the old values and append the values after that to it. But since $(PackageTargetFallback) probably (can't look/dig deeper in right now) have the .NET Framework moniker there, you'll override it with your own values.

Additionally

Given that PackageTargetFallback is now deprecated, one should use AssetTargetFallback instead.

Darkle answered 16/8, 2017 at 11:35 Comment(8)
Entity Framework still seems to install quite happily with "Checking compatibility for EntityFramework 6.1.3 with .NETCoreApp,Version=v2.0." and then I get "All packages and projects are compatible with .NETCoreApp,Version=v2.0."Plentiful
Do you get any warnings while restoring? If yes, you can turn them into errors in project settingsDarkle
Nope no warnings. Clean new project - added EF 6.1.3 - just checks compat for 9 items (inc EF) and then just works (well until you use EF)Plentiful
I should be clear I get warnings on Nuget dependencies view if I look at them - I'm trying to prevent getting that farPlentiful
@Plentiful I just tried this with a project which targets .netCore 1.1 and it failed with a message saying that EF 6.3.1 is incompatible. Is there a difference between .netCore 1.1 & 2.0 or is there another option that is causing this?Coke
@ViktorSeifert .Net Core 2 supports a compatibility shim using to allow .Net Core projects to use assemblies not compiled for .Net standard as long as they support the appropriate APIs #44465437Plentiful
@Darkle just had discussion about analyser at work and we came to that conclusion. Given it is server based analysis be nice if it integrates into nuget install process to inform you or something similar. Hopefully people just update their packages to target standard 2.0.Plentiful
I just realized PackageTargetFallback is deprecated and one should use AssetTargetFallback instead, you could try that and give feedback if it worked better than PackageTargetFallback. I just noticed it because I tried to build my project via command line and the error happend, while Visual Studio didn't complain about it at allDarkle
E
0

As far as I know .Net portability analyzer tool can not 100% determine the platform that does not support installation, such as system.runtime.Loader, after tool analysis, 100% supports the framework platform, but it does not

Screenshot of analysis results:analyse System.Runtime.Loader

Erleneerlewine answered 4/3, 2022 at 7:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.