Closed terrajobst closed 5 years ago
@forki, @terrajobst, @isaacabraham
Yes coreclr is missing a feature.
A bit of history on why downward binding even exists on the desktop:
Before we shipped V1.0 of the CLR there was a scenario that we cared about:
An Application AppA shipped with a dependence on AssemblyB V1.0.0.0. An Application AppB shipped with a dependence on Assembly B V1.0.1.0 and publisher policy Upgrading v1.0.0.0 refs to V1.0.1.0 all policy assemblies and dll's would be installed in the GAC
Now V.1.0.1.0 of B was slightly incompatible with V1.0.0.0 and because of the pub policy AppA was broken.
We actually had in Windows tooling to inject a binding redirect into the app.config for App A, pushing the Binding back down to 1.0.0.0 (it was upgraded by the policy assembly) downgraded again by the binding redirect.
The above scenario was why binding redirects, were designed.
Notice:
Today there is still a scenario that is easy on the desktop and impossible on the coreclr. The coreclr binding policy of not allowing downward binds is what makes it impossible on the coreclr, binding redirects solve it on the desktop CLR
Application A
Library C is unable to work with V1.2.0.0 because of a compatibility bug. Library D could successfully work with Library V1.1.0.0 but the author was foolish and compiled with a higher than necessary version of the library and so an Application cannot successfully compose Library C and Library D.
On the desktop a downward binding redirect would allow an application to compose these libraries by fixing the references to 1.1.0.0. On the Coreclr, there is no combination that will work.
There are two possible solutions:
The first is very hard:
The second is easier:
If I had a vote, my preference would be educating the ecco-system to do the "right thing". However, right now there is a valid binding scenario on the desktop that is impossible to replicate on the coreclr.
Anyway that is my 2 cents.
Kevin
@terrajobst
@FransBouma https://github.com/fransbouma
Ah, I see. Seems like it hasn't bee released through the gallery yet. Go to https://www.nuget.org/downloads and select VS 2015 VSIX v3.6.0 https://dist.nuget.org/visualstudio- 2015-vsix/v3.6.0/NuGet.Tools.vsix . I'll follow up with the NuGet team to see why 3.6 wasn't pushed yet.
Installing that extension indeed made pass that issue (didn't know you could install the nuget client vsix from that site) however then I ran into the issue:
To reference a library that targets .NET Standard 1.5 or higher, you need to install the .NET Standard Build Support extension for the .NET Framework from https://aka.ms/netstandard-build-support-netfx
No idea why, my consoleapp is targeting .net 4.6.2. Well, perhaps for some shims, but really, this isn't a good experience at all. The Nuget client didn't install the package. Installing the 'net standard build support extension' in 2015, restarting the IDE then made Nuget install EF core 2.0 in the .net 4.6.2 targeting consoleapp.
My recommendation would be to push out Update 4 for 2015 with the new nuget and this build extension so people can use .net standard 2.0 stuff in 2015 as they should be able to. How it is now isn't a good experience. Now I personally wouldn't mind people on 2015 not being able to use EF Core 2.0 but that's another story ;) :P
FB
To reference a library that targets .NET Standard 1.5 or higher, you need to install the .NET Standard Build Support extension for the .NET Framework from https://aka.ms/netstandard-build-support-netfx
Well, I guess that answers part of my questions above.
Opening the msi in Orca, I can see the shims (which answers my other question from above, where the shims actually come from) and a few task dlls / targets files.
Imho this is the worst possible deployment model - now I need to update all buildservers and all developer environments, but if I don't they will fail silently.
The previous model, where the shims were deployed with a nuget package (NETStandard.Library.NETFramework) was slightly better from that perspective.
I have a test project (VS2017.3 and after making the changes listed I still get
Reference required to assembly 'System.Runtime, Version=4.0.20.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' containing the type 'ValueType'. Add one to your project.
How do I add this to my project?
Also I can't upgrade any NuGet Package from 2.2 to 2.3.2 without getting too many errors to list. I am targeting 4.6.2 and would like to move to 4.7 and latest CodeAnalysis packages.
@terrajobst
I'm not aware of this issue. Did you uninstall the packages first / did you migrate the contents of the
packages.config
file into thePackageReference
elements?
Oh, now I realized where I made a mistake. My steps to reproduce the issue were:
UnitTest1.TestMethod1()
generated from the template. It should be visible in Test Explorer.packages.config
.<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
there.My problem was: I didn't explicitly reference any Nuget package in test project yet, so I thought there is no need to migrate anything from of packages.config
into the PackageReference
elements. But there are 2 packages referenced by default in packages.config
: MSTest.TestAdapter
and MSTest.TestFramework
. Migrating them manually fixed the problem (so did referencing them via Nuget Manager as I wrote previously).
Sorry for confusion, my mistake.
I just opened an issue in the Xamarin bug tracker here but it seems to be specific to netstandard. I basically converted a Xamarin PCL to netstandard and only using a method from the Newtonsoft.json NuGet package makes the android project throw a compilation exception
Exception while loading assemblies: System.IO.FileNotFoundException: Could not load assembly 'Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'. Perhaps it doesn't exist in the Mono for Android profile?
Is this issue the cause of https://github.com/JamesNK/Newtonsoft.Json/issues/1423?
I logged issue #504, but this maybe seems like a more relevant place to comment.
I have done a bit of playing around, trying to follow the workaround instructions at the top, but even so it still doesn't seem to work.
Here is what I have now done to try and make it all function.
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>MyProject</RootNamespace>
<AssemblyName>MyProject</AssemblyName>
<TargetFramework>net471</TargetFramework>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NETStandard.Library" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="NETStandard2.csproj" />
</ItemGroup>
</Project>
Firstly, I thought that 4.7.1 was supposed to play nice with NetStandard 2.0, but secondly I am still having to add the manual reference which is surely what the nuget package is supposed to be about.
Is there something that I have got wrong from the instructions above - if so, I can't work out what it is.
If anyone has some contact with the team maintaining the Microsoft.Bcl.Build package, there is an error in the package where it checks for the existence of packages.config.
@terrajobst When you said...
My recommendation is: don't add BR via a package manager. We've worked with the NuGet folks to disable their BR generation as well. It should be generated during build, because that's the only place where all the necessary context is available.
... are you suggesting that we check the "Skip applying binding redirects" checkbox here:
The automatic binding redirects is a tooling feature to just generate the redirects in the config file, right? I recall it not working for me in some situations for whatever tooling reason and this caused some pain in the past.
Really, what I would desire on this point is a way to tell the runtime to use whatever name-matching assembly I have thrown into the bin directory. I do not want to the runtime to care about versions - whatever assembly lands in my bin directory is what I want the runtime to use (and if there are multiple, I expect it to error and tell me to get my stuff straight). I do not want "higher wins" or any other "smart logic", I just want "I literally put a DLL file with the right name in the bin directory, just use that to serve your human masters, machine".
@terrajobst
If you currently do have a packages.config, convert the contents to packages references in the project file.
Please update this guidance like below to get the right behavior:
<PackageReference Include="package-id" Version="package-version" />
There seems to be a problem with using Fakes in this new world. If you try to build Fakes for something exposing System.Net.Http.HttpClient
, then it fails to generate. Has anyone found a solution for this?
Error CS0430 The extern alias 'snh' was not specified in a /reference option [D:\Files\Visual Studio 2017\Projects\FakesTest\FakesTest\obj\Debug\Fakes\bcldsc\f.csproj] FakesTest D:\Files\Visual Studio 2017\Projects\FakesTest\FakesTest\f.cs
@Blackbaud-JonathanBell Exactly the same issue for me for the System.Net.Http.HttpClient
. But also it seems to be that System.Composition.CompositionContext
is affected. Any thoughts on this?
The issue appears to be because the generated fakes project produces code that references these assemblies w/ an extern alias --- extern alias snh;
. The generated project references these assemblies like System.Net.Http which are in this weird transition state and defines the alias for it, but since those assembly references actually get ignored due to this transition magic, then the alias isn't recognized.
No clue how to fix it ...
Maybe I am wrong, but it seems to be an compiler issue, isn't it?
From what I read you can pass a flag to the compiler telling it the alias/reference like /reference:snh=System.Net.Http.dll
. This seems not to be the case. Is there an option to pass this flag to the compiler during Fakes generation?
Could it also be that the compiler does not know which System.Net.Http
version to take, when it generates the Fakes? I am using System.Net.Http 4.3.3.0
in a .NetFramework project with .Net 4.7, but maybe there are dependencies left to version 4.0.0.0
. I do use <bindingRedirect>
, though.
Any thoughts?
We have recently migrated a solution from .NET 4.5 to .NET 4.6.1. Many of the nuget packages we consume are now available as netstandard2.0 which is chosen in preference to net45/net46. This is a breaking change for us as we have a solution containing both C# and C++/CLI projects. The latter can't reference netstandard2.0 libraries. Is there any way to force the selection of net45/net46? (e.g. project change). We are still using packages.config.
@rrelyea @emgarten is there a way to force a certain TFM to be used for a packge in a project?
is there a way to force a certain TFM to be used for a packge in a project?
There isn't a way to set the TFM per package, only the project TFM is used.
@emgarten in this case they want to target 4.6.1 but want want the .net framework asset from the package as opposed to netstandard for their C++/ CLI project.
@terrajobst any reason C++/CLI can't be made to work with netstandard?
Many of the nuget packages we consume are now available as netstandard2.0 which is chosen in preference to net45/net46
This shouldn't happen.
If a project is net461 it will favor package assets in this order:
netstandard2.0 would only be used if zero net* assets were available in the package for that asset type. Note that assets are selected individually, so if build has net461 assets but lib only has netstandard2.0 assets then you will still get netstandard2.0 lib assets. It is up to the package author to use the same frameworks for each asset type to make this consistent.
This is true for both PackageReference projects and for packages.config projects.
@davidjward30 sounds like a .NET Framework asset in a package should be preferred over a .NET Standard asset. Is that not what you are seeing?
@Petermarcu @emgarten I've just double checked and I think the problem lies around "portable-net45+win8+wp8+wpa81" which does not appear in your list above.
If I take a .net 4.6.1 framework project (packages.config) and install System.Collections.Immutable 1.4.0, these are the options:
netcoreapp2.0 netstandard1.0 netstandard2.0 portable-net45+win8+wp8+wpa81
.netstandard2.0 is being chosen, where I would expect the last one - particularly as you stated that net45 (same framework) is above netstandard 2.0. FrameworkNuget.zip
Note that System.Collections.Immutable 1.3.1 offers just
netstandard1.0 portable-net45+win8+wp8+wpa81
In this scenario, portable-net45+win8+wp8+wpa81 is chosen. So in summary, upgrading to System.Collections.Immutable 1.4.0 is a breaking change for us.
@emgarten how do the portable TFM's map into the picture? Is this a case where they were mapped to .NET Standard so .NET Standard is winning?
Just to summarize what @davidjward30 is pointing out:
1.3 had: netstandard1.0 portable-net45+win8+wp8+wpa81
1.4 had: netcoreapp2.0 netstandard1.0 netstandard2.0 portable-net45+win8+wp8+wpa81
So 1.4 added: netcoreapp2.0 netstandard2.0
and netcoreapp2.0 is winning over portable-net45+win8+wp8+wpa81
Should 1.4 have included assets for each specific TFM it used to support in order to prevent this from being a breaking change because portable isn't treated as more specific than .NET Standard?
@davidjward30 the workaround for this is to modify the hint path in your csproj file to reference the portable folder instead of the netstandard2.0 folder in the package. For packages.config projects it is easy to override the tfm selection this way.
portable-*
frameworks are the lowest priority when selecting assets, which is why netstandard2.0
is selected from 1.4.
The reason portable-net45+win8+wp8+wpa81 (profile 259)
wins over netstandard1.0
is because that portable framework is a special case and able to install netstandard1.0
packages. The table of these portable frameworks with netstandard equivalents is here: https://github.com/dotnet/standard/blob/master/docs/versions.md
I can see how this is a problem for C++ projects, but for most users netstandard2.0
should be a larger surface area over the legacy portable profile 259 unless I'm missing something.
We have a fairly large codebase of 150+ projects. The workaround of modifying the hint path would probably have to be scripted and I'm not sure how long we could continue like that. Is this a workaround we would have to live with indefinitely? We also have plans to move to packagereference
@davidjward30 you could try updating all references through an msbuild props/targets file that fixes the hint paths.
I see this with .NET Standard 1.4 projects as well using PackageReference. I have a JavaScript UWP app using a Windows Runtime Component which references the .NET Standard libraries and the Nuget dlls don't get copied as part of the build.
Can I update the UWP JavaScript project which default template used package.json to use PackageReference or is that only for pure .NET projects?
Any ideas how to fix https://github.com/RevenantX/LiteNetLib/issues/120 above? The binding redirects didn't help (or I did something wrong).
@tomzorz
I responded to the issue. Your issue has definitively nothing to do with this issue here as you're using .NET Core and .NET Standard. Binding Redirects are a .NET Framework only thing. It looks like the package you're consuming is authored incorrectly.
@michael-hawker
I see this with .NET Standard 1.4 projects as well using PackageReference. I have a JavaScript UWP app using a Windows Runtime Component which references the .NET Standard libraries and the Nuget dlls don't get copied as part of the build.
Can I update the UWP JavaScript project which default template used package.json to use PackageReference or is that only for pure .NET projects?
I haven't looked into UWP and JavaScript consuming a managed WinMD. Are you using a project-to-project reference between the JavaScript project and the C# UWP WinMD project?
@terrajobst Yes, I have the WinMD component project referencing the .NET Standard component, and then the JavaScript UWP project referencing the WinMD component project.
@terrajobst ah thanks, I wondered if it was relatable to this one! Appreciate the help!
After moving to PackageReference
(and toying with AutoGenerateBindingRedirects
and GenerateBindingRedirectsOutputType
), I am still running into a FileNotFoundException
.
I am using the Pkcs11Interop NuGet package, which requires netstandard13 or net4. It is referenced from LibraryProject, which is netstandard2. That project, in turn, is referenced from WebProject, which is net471.
When building and running WebProject, it outputs Pkcs11Interop.dll
, but at runtime it tries to load Pkcs11Interop.NetStandard.dll
!
Which DLL should be used? I would assume the netstandard one, as the direct consuming project is netstandard.
How do we get the compile time and runtime behaviors to play nice?
Edit: It seems likely that this happens for all similar packages, but that the problem usually stays hidden because the file names are usually identical.
Still hitting this in 2018. What's the plan to make this suck less?
Ditto
The short-term plan for (1) is to start blocking project-to-project references in Visual Studio 15.4 that will end up crossing the streams between packages.config and PackageReference
Visual Studio 15.5.7 here and there is still no block in the UI to prevent you from doing that crossing.
I added the RestoreProjectStyle
without taking too much time to understand it properly after finding it here while I was starting my first project with .Net Standard (thanks for it anyway @shanselman :) ). In fact I didn't realize I had to get ride off the packages.config
file and reinstall all my NuGets by adding references back to the .csproj instead.
So now back to get ride off packages.config
to fix my solution and crossing my finger to not hit any of those limitations and... Oh wait... of course I have packages that use a powershell script, which is not supported yet!!!
If at least the mentioned block in the UI had been there I would have noticed I did something wrong. Instead I learnt about that issue the hard way! I have been waiting for almost 2 years prior to give a try to .Net Core and .Net Standard, thinking it will give them the required time to get mature. Looks like I was wrong and my only workaround now seems to back off .Net Core in my entire solution.
i share @ggirard07 sentiment. I tried netstandard and hibrid project format approach since mid 2017 and it has way too many gotchas, it's a shame because the new project system is so much better, but this friction does not really allow incremental upgrades of solutions, maybe it's not meant to be, but it's a shame 😄
I am new to Visual Studio 2017 and getting a warning in my xamarin project as below Warning NU1701 Package 'ZXing.Net.Mobile 2.3.2' was restored using '.NETFramework,Version=v4.6.1' instead of the project target framework '.NETStandard,Version=v2.0'. This package may not be fully compatible with your project. Please help me to resolve this issue.......a lot has been suffered by me on this.Please help
@pankajmishra743 your project is targeting .NET Standard 2.0, but ZXing.Net.Mobile
is only built for .NET Framework 4.6.1, worth asking the package authors as this issue isn't the place to get help for things like that.
Also worth reading https://docs.microsoft.com/en-us/dotnet/standard/net-standard to familiarize yourself with what .NET Standard is. Scott Hanselman also has a pretty good blog post that summarises (or did summarise, for 2017) the state of .NET Standard/Core/Framework/etc: https://www.hanselman.com/blog/WhatNETDevelopersOughtToKnowToStartIn2017.aspx
Hitting this after converting a .net framework console exe to the new sdk format even though that is supposed to set up the binding redirects automatically. At least I assume I am, a MethodNotFoundException from a referenced .net standard project when it tries to call out to a DLL in a nuget package even though that DLL is in the output folder.
I think it may be related to the ValueTuple shenanigans where the referenced library uses v1.3.x and the consuming library uses v1.4.0
I know I am joining this late but the argument that .NET 4.7.1 in some way provides a solution is not satisfying given that we have very recently been told by Microsoft that:
1- For Azure VM scale sets there are no plans to support 4.7.1 with Windows Server 2016 2- For Azure Cloud Services there are no plans to ship 4.7.1 with Web/Worker roles
@FransBouma I had the same problem using NetStandard.Library v2.0.1: The Assembly Binding Log Viewer (aka fuslogvwr) tell me that the assembly loader was unable to load 'System.Threading.Overlapped, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' because cannot find this specific version of this assembly. The same assemly was available with higher major / minor version numbers.
I had this problem for other dlls.
The 'Il Disassembler' (ILDasm) show me that NetStandard.Library v2.0.1 references versions numbers 0.0.0.0 for many other dlls:
To resolve this problem I had to add some binding redirect to my app
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Overlapped" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
I will evaluate use of AutoGenerateBindingRedirects.
This problem reported by a user of one of my libraries here: mj1856/TimeZoneConverter#16. Note that the binding redirect isn't an option since strong naming is not a thing for me, per .net core guidance here, and binding redirects do not work without a strong name token (I think).
@terrajobst - I'm confused by the workaround mentioned at the top. Should I just be able to add <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
to my .net standard class libraries that are published to nuget? I experimented locally, but it doesn't seem to work.
Manually adding a binding redirect in the end-user application does work, but no amount of fiddling with the settings on my side seems to force a binding redirect be created in the end-user's application when they pull in my packages. What am I missing?
Thanks. -Matt
This setting needs to be set in the project that packages are installed into.
@sandersaares - tried that. Got bindings generated for Newtonsoft, but not for my library.
Is it just me, or is the migration path from Framework
to Standard
/Core
(anything, 1.x
, 2.x
, etc) a maze that, personally, I'm finding fairly difficult, at best, to navigate, if not downright confusing. In my case, I want to dive into potentially a Roslyn compile time code generation analyzer, but I'm finding that the minimum requirements for that are at least .NET Standard 1.x
? Perhaps, it seems there is a plausible bridge from Framework 4.6.x
targeted projects along these lines? Or at least from my Analyzers
project(s), per se. Thoughts? Suggestions? Recommendations? Thanks!
Summary
We've designed .NET Standard & our tooling so that projects targeting .NET Framework 4.6.1 can consume NuGet packages & projects targeting .NET Standard 2.0 or earlier. Unfortunately, we've seen a few issues around that scenario. The purpose of this document is to summarize the issues, outline our plan on addressing them, and providing workarounds you can deploy with today's state of our tooling.
Symptoms and root cause
The primary symptom is that applications crash with a
FileLoadException
or aFileNotFoundException
. Another symptom is warnings at build time regarding assembly versions. This is due to one or both of the following issues:Missing binding redirects
.NET Standard 1.x was based around contracts. Many of these contracts shipped with .NET Framework 4.5 and later. However, different versions of .NET Framework picked up different versions of these contracts, as by-design of contract versioning. As a side effect of marking .NET Framework 4.6.1 as implementing .NET Standard 2.0, some projects will now start picking up binaries built for .NET Standard 1.5 and 1.6 (as opposed to previously where .NET Framework 4.6.1 was considered as implementing .NET Standard 1.4). This results in mismatches of the assembly versions between what was shipped in .NET Framework and what was part of .NET Standard 1.5/1.6.
This can be addressed by binding redirects. As writing them by hand sucks, we added an Automatic Binding Redirect Generation feature in .NET Framework 4.5.1. This feature is opt-in. Unfortunately, it's not enabled based on target framework, but by which target framework was selected when the project was created (as the feature is turned on via an MSBuild property that is conditionally emitted by the template). In practice, this means it's mostly off if you often upgrade existing projects, rather than creating new ones.
Missing binaries
There are two primary flavors of NuGet:
packages.config
andPackageReference
.With
packages.config
, each project has a config file with a flattened graph of all the NuGet dependencies. The project file in turn has direct links to all the assets. The assets are selected at install time. None of this includes indirect NuGet references coming from referenced projects.With
PackageReference
each project contains MSBuildPackageReference
items. The project file contains no references to any assets as the assets are selected at build time. Package restore will compute the graph of all packages, including indirect NuGet references coming from referenced projects.The default for .NET Framework projects is
packages.config
. This ensures more compatibility becausePackageReference
doesn't support all the features thatpackages.config
did, for example, PowerShell install scripts and content.The only supported mode for SDK-style projects (.NET Core/.NET Standard) is
PackageReference
. This means that a .NET Framework project referencing a .NET Standard project ends up crossing the streams between two different NuGet models. When the .NET Standard project references NuGet packages that the .NET Framework project doesn't reference, the application ends up missing all binaries coming from those packages.Why has this worked before? Because with
packages.config
, all dependencies are copied to each project's output folder. MSBuild copies them up from there. WithPackageReference
, we don't copy the binaries because it relies on the consuming project to see its dependencies and extract the proper asset itself. This allows the consuming project to pick up the right assets for packages that use bait & switch (which many of the .NET packages must do).Plan
The plan is to address these issues moving forward as follows:
Converge on
PackageReference
for all project types, including .NET Framework. The short-term plan for (1) is to start blocking project-to-project references in Visual Studio 15.4 that will end up crossing the streams betweenpackages.config
andPackageReference
. This block is UI only; you can still edit the reference by editing the project by hand. The error message will instruct you to switch the .NET Framework project toPackageReference
if you want to reference a .NET Standard project. Referencing .NET Standard binaries or NuGet packages will not require this, it's only about project-to-project references. In later releases, we plan on providing a converter. The challenge is thatpackages.config
has features we can't offer forPackagReference
across the board, in particular PowerShell install scripts and content. We'll need good guidance and mitigations, if applicable.Ensure binding redirects are on by default. Short term, this means we need to fix our target files to make sure we turn on automatic binding redirect generation. However, binding redirects don't work well in all scenarios, when there is no application project (like unit tests or add-ins). We need to work on a plan to bring the regular “higher wins” binding policy without binding redirects. This needs a proposal and proper vetting, but it seems we've reached the point where this is necessary.
Workarounds
Regular .NET Framework projects
packages.config
but usesPackageReference
for NuGet packagespackages.config
, simply add<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
to your project filepackages.config
, convert the contents to packages 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.config
file.PackageReference
like mentioned above. In web sites, you cannot usePackageReference
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 tests 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
: