Standard: Issues with .NET Standard 2.0 with .NET Framework & NuGet

Created on 2 Sep 2017  ·  163Comments  ·  Source: dotnet/standard

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 a FileNotFoundException. Another symptom is warnings at build time regarding assembly versions. This is due to one or both of the following issues:

  1. Missing binding redirects
  2. Missing binaries that come from indirect NuGet packages

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 and PackageReference.

  • 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 MSBuild PackageReference 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 because PackageReference doesn't support all the features that packages.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 withpackages.config, all dependencies are copied to each project's output folder. MSBuild copies them up from there. With PackageReference, 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:

  1. 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 between packages.config and PackageReference. 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 to PackageReference 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 that packages.config has features we can't offer for PackagReference across the board, in particular PowerShell install scripts and content. We'll need good guidance and mitigations, if applicable.

  2. 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

  1. Enable automatic binding redirects in the root .NET Framework application.
  2. 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> to your project file

    • If you currently do have a packages.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

  1. 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.
  2. 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 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:

<PropertyGroup>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
announcement

Most helpful comment

Still hitting this in 2018. What's the plan to make this suck less?

All 163 comments

Thanks for this, things do seem a little unpolished, so it's useful to have some clarity.

Other things that currently make it painful for us to mix .net framework with .net standard are a FileNotFoundException that will make it difficult for us to migrate our internal packages in a safe way: https://github.com/NuGet/Home/issues/5715 and the lack of visibility of indirect packages when switching to PackageReferences: UserVoice to convert all projects to new common project format

Is it correct that PackageReference is not supported for anything other than .net core, .net standard and UWP? See the documentation:

At present, package references are supported in Visual Studio 2017 only, for .NET Core projects, .NET Standard projects, and UWP projects targeting Windows 10 Build 15063 (Creators Update).

Hopefully that will change in future as it is an option in Visual Studio and is the workaround that you describe.

Hi @terrajobst, is there a document detailing which scenarios are supported for .NET Framework 4.6.1 and .NET Standard 1.6?

I created a net461 old-sdk project in VS2017.3 and added a .NET Standard 1.6 NuGet. The build automagically copied the required shims to the output, totalling 100 files. ✅

If I open the exact same project in VS2015 and build, the output contains only 4 files, so the shims are missing. ❌


Where do the shims come from, anyway? I was following some earlier discussions, and I know at first they were deployed via a NuGet package. But later discussions talked about some machine-wide installation. What was the final result? What do we need to deploy to a build server to enable this scenario?

@mungojam

Is it correct that PackageReference is not supported for anything other than .net core, .net standard and UWP?

You can use PackageReference in .NET Framework projects, but as I outlined there is a loss in certain features. For instance, if you install packages that rely on PowerShell scripts (for instance, EF6) they will no longer work. Also, packages that require content (i.e. source files that are copied to the consuming project) they will also no work.

@0x53A

Which NuGet package are you consuming? For .NET Standard 1.x, the package is supposed to depend on NETStandard.Library which will bring in the shims.

@terrajobst repro is here: https://github.com/0x53A/n16test

The nupkg was created calling "dotnet pack" on
https://github.com/0x53A/n16test/blob/75fcfdc0d540531c30b805e74bb239e42d13ffea/ns16lib/ns16lib.csproj#L1-L7.

The resulting package looks like this:
image

To reproduce my issue:

1) open https://github.com/0x53A/n16test/blob/master/net461exe/net461exe/net461exe.sln in VS 2017.3 and build.
2) note that /bin/ contains 100 files.
3) clean /bin/, re-open in VS 2015.3 and build
4) note that /bin/ contains only 4 files.

In vs2015, in a csproj targeting v4.6.2, I wanted to add a reference to Entity Framework Core 2.0, but that failed with this error:

Attempting to gather dependency information for package 'Microsoft.EntityFrameworkCore.SqlServer.2.0.0' with respect to project 'EF Core 2\NWEFCore2.Persistence', targeting '.NETFramework,Version=v4.6.2'
Gathering dependency information took 0,87 ms
Attempting to resolve dependencies for package 'Microsoft.EntityFrameworkCore.SqlServer.2.0.0' with DependencyBehavior 'Lowest'
Resolving dependency information took 0 ms
Resolving actions to install package 'Microsoft.EntityFrameworkCore.SqlServer.2.0.0'
Resolved actions to install package 'Microsoft.EntityFrameworkCore.SqlServer.2.0.0'
Retrieving package 'Microsoft.EntityFrameworkCore.SqlServer 2.0.0' from 'nuget.org'.
Install failed. Rolling back...
Package 'Microsoft.EntityFrameworkCore.SqlServer.2.0.0' does not exist in project 'NWEFCore2.Persistence'
Package 'Microsoft.EntityFrameworkCore.SqlServer.2.0.0' does not exist in folder 'C:\Myprojects\VS.NET Projects\LLBLGen Pro v5.3\UnitTests\EntityFramework\packages'
Executing nuget actions took 62,07 ms
install-package : Could not install package 'Microsoft.EntityFrameworkCore.SqlServer 2.0.0'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.6.2', but the package does not contain any assembly references or content fi
les that are compatible with that framework. For more information, contact the package author.
At line:1 char:1
+ install-package Microsoft.EntityFrameworkCore.SqlServer
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
    + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand

Likely a bug in the Nuget client in 2015 (but I am under the assumption I have the latest version installed), but IMHO this should simply work as .NET 4.6.2 supports .NET standard 2.0

(edit) This does work in vs2017 15.3.x. That's not an excuse to not fix this! Many devs are on 2015 and have no plans to move to 2017 (yet) and as .net standard 2.0 is supported on .net 4.6.2, they should be able to expect this to just work.

I don't know if this is the right location to file this (likely not!), if not please point me to the repo where I should file this, thanks.

cc @forki I wonder what impact this has on Paket vis-a-vis automatic binding redirects (Paket has the option to generate BRs on demand based on the dependency graph).

@terrajobst If there's a BR already in the app.config file and you turn on the automatic BR redirection, who wins?

@isaacabraham I have no idea. this will bring interesting new problems to us.

And another problem:

Using EF Core 2.0 in a .NET 4.6.2 project: as soon as you create a DbContext derived type, you'll get this error:

System.IO.FileLoadException : Could not load file or assembly 'System.ValueTuple, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
  Exception doesn't have a stacktrace

Likely caused by the same issue as the ValueTuple containing assembly isn't there. This is in vs2017 15.3.x btw.

Brb, throwing some heavy furniture against the wall screaming.

@FransBouma This looks familiar: https://github.com/dotnet/standard/issues/476#issuecomment-326726613

How about dropping this scenario and make it work "cleanly" with a future version instead of trying to get with the head through the wall?

Note that the binding redirection documentation is missing the critical

<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>

property which is crucial to making "classic" test projects work (as well as libraries loaded via reflection).

@0x53A yes, I think that's similar. The bindingredirect however kills nunit for some reason (the test is now simply not seen by it and not run).

@dasMulli Thanks for that, but I am at a loss where to add that... adding it to the bindingredirect nor the csproj etc. does make nunit work again.

And here I am hoping that after weeks of fighting with MS pre-alpha quality tooling (Where's the QA testing? We paid for this software!), this week would go smoothly. Nope

(edit) fsck it, converting to new csproj format, perhaps that gives some results.

(edit) for ref: https://github.com/dotnet/sdk/issues/1070 adding the 2 redirects made nunit work again. With the new csproj format the bindingredirect isn't needed, the valuetuple issue isn't popping up, but the attribute referred by @dasMulli are required to make things work.

Man... one could start wondering what 'alpha' quality means these days if 'RTM' is this quality.

On the announcement, the "primary symptom" link is broken (via @forki )

image

@FransBouma I wasn't directly referring to your problem but rather pointing out that the official documentation and announcement issue lacks this information (cc @terrajobst).

For VS 2015, there is an additional extension to install for .NET Standard 2.0 support - When using NuGet 3.6.0, it will print out the link. However, I've tried it but it is currently broken anyway for most scenarios: https://github.com/dotnet/sdk/issues/1539

@dasMulli oh sorry about that, but in any case it helped me a lot, so thanks for your input :)
Yeah I think 2015 is a lost cause at the moment. Thanks for referring to the nuget link, I didn't know I had to install a separate extension. In my 2015 installation it didn't mention that.

When you say

simply add PackageReference to your project file

I'm assuming this means the csproj has to use the VS2017 style csproj, as in, it needs to start with <Project Sdk="Microsoft.NET.Sdk"> and it needs to be built using msbuild 15 or the dotnet cli, right? Only working in Visual Studio is not much use for everyone (and I hope this is the majority) who use CI/CD pipelines. So this means that we can't really use netstandard nugets without converting the csproj file to vs2017 style.

@mariusGundersen all csproj format ("classic" + "sdk-style") can use PackageReference items since VS 2017 15.2. NuGet tries to detect if there is any <PackageReference> item in the project or if there is a packages.config in the project to determine which "restore style" is to be used.

However, if neither of those are present, the <RestoreProjectStyle> can be set to PackageReference to enable all features of projects using this style. This then enables transitive dependencies from referenced projects also using PackageReference. The "sdk-style" (<Project Sdk="Microsoft.NET.Sdk">) projects already set this by default.

So I need to install the latest nuget client on the build server to be able to use <PackageReference>? And I guess that as long as the project file is still classic style it needs the <Reference> and <HintPath> to work?

@0x53A

Thanks for the repo, we'll take a look.

@FransBouma

Make sure you have the latest NuGet client for VS 2015. It looks your client doesn't know that .NET Framework 4.6.1 supports .NET Standard 2.0. If the error persist after upgrading, I'd file a bug in the NuGet org (https://github.com/NuGet/Home/issues/new).

@isaacabraham and @forki

I wonder what impact this has on Paket vis-a-vis automatic binding redirects (Paket has the option to generate BRs on demand based on the dependency graph).

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. If anything, I'd consider making Paket add the AutoGenerateBindingRedirects property to the project file if it isn't set already.

Eventually, I'd like the desktop binder to do the right thing here, but we'll see whether we can actually pull this off...

If there's a BR already in the app.config file and you turn on the automatic BR redirection, who wins?

The automatic binding redirect feature will attempt to merge them. Generally speaking, manual BRs will be honored and win.

@matthid

How about dropping this scenario and make it work "cleanly" with a future version instead of trying to get with the head through the wall?

What would you do differently from what I outlined in the plan above? To me, the plan is precisely what you're asking for.

@dasMulli

Excellent point. Fixed.

@mariusGundersen

When you say

simply add PackageReference to your project file

I'm assuming this means the csproj has to use the VS2017 style csproj

No, you can use non-SDK style projects with PackageReference.

@terrajobst when you say "No, you can use non-SDK style projects with PackageReference" does this mean I can just delete my packages.config and then in my .csproj remove the hint paths and replace with PackageReferences and it'll just work (provided I'm on the correct NuGet version)?

Or is there some other magic you need to do to use PackageReference with non-SDK style projects?

Actually we often set it to make sure nuget/build does not mess with what
we intended (or at least to know when that happens). As double-entry
bookkeeping if you will. Now this usecase is basically broken - or in some
sense you are basically removing all use cases of the redirects if you make
the automatic all the time.

Am 04.09.2017 9:48 nachm. schrieb "Scott Sauber" notifications@github.com:

@terrajobst https://github.com/terrajobst when you say "No, you can use
non-SDK style projects with PackageReference" does this mean I can just
delete my packages.config and remove the hint paths and replace with
PackageReference and it'll just work (provided I'm on the correct NuGet
version)?

Or is there some other magic you need to do to use PackageReference with
non-SDK style projects?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/dotnet/standard/issues/481#issuecomment-327020442,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AADgNOBR7y8_ejww5Pg3tcM878YaubHQks5sfFQPgaJpZM4PKtHI
.

@terrajobst

How about dropping this scenario and make it work "cleanly" with a future version instead of trying to get with the head through the wall?

What would you do differently from what I outlined in the plan above? To me, the plan is precisely what you're asking for.

I appreciate the response. Well yes you are dropping packages.config support. But I meant dropping the compatibility of net461 with netstandard20 from the compatibility table and remove all the special handling around this. This would be the honest way of saying: "Well the runtime did not ship with the proper support for netstandard20 but a future version will". What are the reasons which justify the amount of pain you put everyone through and the amount of effort it generates everywhere (not only internally in Microsoft but also externally like in Paket). There must be really important reasons to have this single compatibility connection but I have no clue what they are.

Could this been fixed with net462 or net463? Maybe I'm missing something here.

@scottsauber

when you say "No, you can use non-SDK style projects with PackageReference" does this mean I can just delete my packages.config and then in my .csproj remove the hint paths and replace with PackageReferences and it'll just work (provided I'm on the correct NuGet version)?

Two options: remove the packages.config and convert all package references by hand as explained above. You can also control the default for .NET Framework works via Tools | Options | Package Manager | General.

@matthid

But I meant dropping the compatibility of net461 with netstandard20 from the compatibility table and remove all the special handling around this.

Believe me, no one on my team is keen on on the way the net461 support story has unfolded. In a sense, what you're asking has already been implemented: .NET Framework 4.7.1 will ship with full built-in support of .NET Standard 2.0. The challenge is that (1) it hasn't been shipped yet and (2) many of our customers will not be able to upgrade immediately because the target environment is outside their control. The option was to support it the best we can or can it altogether. Yes, this unfortunately requires jumping through hoops but at least there is something app developers can do. If you fully control the environment, by all means, jump to .NET Framework 4.7.1.

@forki

Actually we often set it to make sure nuget/build does not mess with what we intended (or at least to know when that happens). As double-entry bookkeeping if you will. Now this usecase is basically broken - or in some sense you are basically removing all use cases of the redirects if you make the automatic all the time.

The problem with double bookkeeping is that automatic binding redirect generation has to assume the project owner knows best and has to honor the BRs that are present. I don't know Paket well enough, but with NuGet we had the issue that NuGet assumed that the same package & version will have consistent assembly versions and not generate redirects based on the referenced assemblies but based on whether package versions differed. If Paket gets it right a 100% then there is arguably nothing against it, but I'd also argue nothing in favor of it either. Outside of .NET Framework you already rely on the binding behavior that higher wins. A generated app.config with the right redirects will do the same, so I don't see a reason why a checked in copy with the project is helping. I just think it causes noise and adds potential for conflicts...

Binding redirects where the only way to protect against the issue that
nuget can have multiple versions of the same package in the repository and
to make sure the right one was selected. Without explicit redirects this is
gone and the flaw in the package manager model is still there.

@isaac_abraham I think the issue is not really related to paket since we
only added them when the user asked for it. Or at least I can't really see
the implications yet. But one thing is for sure - all these changes are not
feeling sound yet. But that's probably only my personal feeling.

Am 05.09.2017 1:33 vorm. schrieb "Immo Landwerth" <[email protected]

:

@forki https://github.com/forki

Actually we often set it to make sure nuget/build does not mess with what
we intended (or at least to know when that happens). As double-entry
bookkeeping if you will. Now this usecase is basically broken - or in some
sense you are basically removing all use cases of the redirects if you make
the automatic all the time.

The problem with double bookkeeping is that Automatic Binding Redirect
generation has to assume the project owner knows best and has to honor the
BRs that are present. I don't know Paket well enough, but with NuGet we had
the issue that NuGet assumed that the same package & version will have
consistent assembly versions and not generate redirects based on the
referenced assemblies but based on whether package versions differed. If
Paket gets is right a 100% then there is arguably no reason nothing against
it, but I'd also argue nothing in favor of it either. Outside of .NET
Framework, you already rely on the binding behavior that higher wins. A
generated app.config with the right redirects will do the same, so I don't
see a reason why a checked in copy with the project is helping. I just
think it causes noise and potential for conflicts...


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/dotnet/standard/issues/481#issuecomment-327039160,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AADgNIDuw8N8Nn9S0egMUPdu9bfDds8Vks5sfIjfgaJpZM4PKtHI
.

If what @terrajobst is saying is that simply adding that single element to a vbproj, fsproj or csproj magically fixes all binding redirects, all the time, then I'm not averse to using that instead and deprecating Paket support for BRs. But only if this works consistently and can be applied to e.g. net452 projects running on old MSBuild project format.

magically fixes all binding redirects

think about what that means. It means there are effectively no binding redirects anymore.
So in some sense the feature is gone.

Doesn't it just mean that the redirects are calculated by the runtime to just promote all assemblies to the version that actually is being used?

that's effectively the same thing, right? It "calculates a redirect to what it actually uses" - what sense does that even make? It's not "redirecting" anything or checking against an external file if what it uses is what was intented.

@forki, @isaacabraham

I may think of binding redirects slightly differently to you. I'm not sure that I do, but your last questions, indicates a slight difference I think.

I don't think of it as impacting an assembly, I think it impacts the reference to the assembly.

_The binding redirect in an app config file, is a policy statement to the runtime. It says to the runtime, when after applying all versioning policies you see an assembly reference in the range MIN to MAX, go and set the version of the reference to X._

What the AutoGenerateBindingRedirects build property does, is to calculate during the build the highest version number of an assembly by examining /r: assemblies and their referenced dependencies. If it sees multiple values for an assembly version, it generates a binding redirect in the app-config to ensure that users of the application doesn't see assembly load errors, because of version mismatches. It then requires the developer to ship this 'highest referenced version' with the app. The build will of course ensure that this is the version copied to the output directory, to make it easy for the developer to identify the correct dll to ship.

I hope this helps, it is for sure how I think of this stuff.

Kevin

Regarding Unit Test projects (as I already mentioned in dotnet/sdk#901):

I'm using VS2017 15.3.3 and .NET Core 2.0.0 SDK. Solution consists of:

  • Project A - .NET Standard 2.0 class library; referencing Newtonsoft.Json via Nuget
  • Project B - .NET 4.6.1 unit test project; referencing A

I'm hitting FileNotFoundException in B. As a workaround, I put

<PropertyGroup>
  <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>

in B's project file. Using <RestoreProjectStyle>PackageReference</RestoreProjectStyle> has side effect though: all tests in B disappears from Test Explorer window. To fix this issue, I had to upgrade test adapters and test framework via nuget as described here.

Is this intended behavior of package reference or a bug? Either way, I think others might experience it, so I would suggest to update workaround info above.

@KevinRansom

yes I do understand redirects and their influence on the runtime ;-)
I never said it would influence an assembly.

I think it boils down to the recurring theme that I (and others) happen to use it in a different way than many MS employees may do. For me it makes absolutely no sense to let the build automate it, because then we could just throw it away completely or at least gitignore it or something.

For me it's a way for users to make sure the the build (and deploy!) process is doing the right thing and in the end we have the correct version of the assembly loaded into our program.
This is especially important when you have a bigger solution and many dependencies. In such cases we often saw just one version of an assembly (like FSharp.Core/newtonsoft) win and then in the end we had MissingMethodExceptions all the time.
We then made sure package management worked and only uses one package in the whole repo - but even that wasn't enough. So binding redirects where needed so that at least at app start you know if things are still sane.

@terrajobst

Make sure you have the latest NuGet client for VS 2015. It looks your client doesn't know that .NET Framework 4.6.1 supports .NET Standard 2.0. If the error persist after upgrading, I'd file a bug in the NuGet org (https://github.com/NuGet/Home/issues/new).

here's the thing, in vs2015, I have nuget extension v3.5.1484 installed, but if I browse to the gallery in vs2015 and search for 'nuget' I see it offers v3.4.4.1321. vs 2015 itself doesn't say I need to update the client. The gallery states it's been updated on 6/3/2016 (that's more than a year ago) and the one in vs2015 has been updated on 10-11-2016.

This is in vs2015 update 3. (v14.0.25431.01). AFAIK there's no update 4 for vs2015, and the build of nuget client for vs2015 is very old. I can now go over to the nuget repo and have an unpleasant conversation with the folks over there, but I think there's something else not right: where is the updated client for nuget for 2015?

TIA

I understand.

What algorithm would a developer to use to determine which version of an assembly is correct, given a solution with many dependencies?

Is it something other than : “The highest version of the assembly discoverable during the build”?

@KevinRansom the problem is that you might still implicitly break something e.g. imagine you have two projects A and B. A depends on V1 of dep, B depends on V2. At runtime you pick V2, as it's the higher one. But V2 introduced breaking changes compared to V1 - either behavioural (different code paths), or structural (different interface, change of method signatures).

What happens at runtime when Project A tries to call a method that was in V1 but doesn't exist in V2 any more? Boom - MissingMethodException.

Is it something other than : “The highest version of the assembly discoverable during the build”?

yes definetely. because that is often just a mistake. Consider you have 100 projects in your sln. All of them use Newtonsoft (which is not that unlikely). Now one upgrades it version from 5.x to 10.x for some (maybe even good) reason.

Now 99 compile against v5 and one against v10 - these are clearly not compatible in any way. It's just a matter of time until something crashes. And there is no resolution to this. "Highest" is as good as "pick one at random" here.

What uses can do is add an binding redirect to the app project that ensures that everything points to v5 (because that's the one we blessed). If the build now ships v10 then you know this "earlier" during deploy and not during on call night hours.

Of course even this is not a perfect solutions since there are still endless ways to mess up, but practice showed that these tricks work very effectively against common human errors.

Yep,

relying on increasing version numbers places a compatibility burden on developers of long-lived libraries. You are certainly more likely to have missing method exceptions if you downgrade a reference from V2 to V1. The old policy assemblies were abandoned (or at least deprecated) before we even shipped V1.0 of the CLR, because of the complexity of getting the definition of it right.

The coreclr resolver won’t satisfy a higher reference with a lower assembly version, although I suppose a custom loadcontext may circumvent that policy.

For developers who want a simpler and likely correct experience a simple tooling experience such as AutoGenerateBindingRedirects seems like a reasonable approach. For the developer who wants explicit control, she can turn it off, and do it manually, or use tools to help them with another approach such as paket.

Kevin

I like the use of "likely correct" - that's exactly what this whole thing
feels in regards to soundness. ;-)

Am 05.09.2017 10:48 vorm. schrieb "Kevin Ransom (msft)" <
[email protected]>:

Yep,

relying on increasing version numbers places a compatibility burden on
developers of long-lived libraries. You are certainly more likely to have
missing method exceptions if you downgrade a reference from V2 to V1. The
old policy assemblies were abandoned (or at least deprecated) before we
even shipped V1.0 of the CLR, because of the complexity of getting the
definition of it right.

The coreclr resolver won’t satisfy a higher reference with a lower
assembly version, although I suppose a custom loadcontext may circumvent
that policy.

For developers who want a simpler and likely correct experience a simple
tooling experience such as AutoGenerateBindingRedirects seems like a
reasonable approach. For the developer who wants explicit control, she can
turn it off, and do it manually, or use tools to help them with another
approach such as paket.

Kevin
From: Isaac Abraham [mailto:[email protected]]
Sent: Tuesday, September 5, 2017 1:31 AM
To: dotnet/standard standard@noreply.github.com
Cc: Kevin Ransom Kevin.Ransom@microsoft.com; Mention <
[email protected]>
Subject: Re: [dotnet/standard] Issues with .NET Standard 2.0 with .NET
Framework & NuGet (#481)

@KevinRansom com/?url=https%3A%2F%2Fgithub.com%2Fkevinransom&data=02%
7C01%7CKevin.Ransom%40microsoft.com%7C3d62daffa0e44ee2653408d4f4387f54%
7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636401970887004067&sdata=
508t4AGiqOn3kEDsTzfSDxWmyvB5MXBSbLvE57zeqsc%3D&reserved=0> the problem is
that you might still implicitly break something e.g. imagine you have two
projects A and B. A depends on V1 of dep, B depends on V2. At runtime you
pick V2, as it's the higher one. But V2 introduced breaking changes
compared to V1 - either behavioural (different code paths), or structural
(different interface, change of method signatures).

What happens at runtime when Project A tries to call a method that was in
V1 but doesn't exist in V2 any more? Boom - MissingMethodException.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub protection.outlook.com/?url=https%3A%2F%2Fgithub.com%
2Fdotnet%2Fstandard%2Fissues%2F481%23issuecomment-327108370&data=02%7C01%
7CKevin.Ransom%40microsoft.com%7C3d62daffa0e44ee2653408d4f4387f54%
7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636401970887014069&sdata=
YikhPPjPtyOOuxNp7WbwpEld5uQVw6686jA%2BOrS2j9M%3D&reserved=0>, or mute the
thread https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%
2FAE76FkkpgTEjX7a2rYZh11xDTpfmiRtXks5sfQbcgaJpZM4PKtHI&data=
02%7C01%7CKevin.Ransom%40microsoft.com%7C3d62daffa0e44ee2653408d4f4387f54%
7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636401970887014069&sdata=
qbNJMpbkokxH27LX4C2vRXzn5mPsSWmw7D3zjVtjUqw%3D&reserved=0>.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/dotnet/standard/issues/481#issuecomment-327112382,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AADgNDJVSkCtNlmcv8dd2IGzIApcDWQSks5sfQrMgaJpZM4PKtHI
.

Yes I used a caveat, but so did you::
_Of course even this is not a perfect solutions since there are still endless ways to mess up, but practice showed that these tricks work very effectively against common human errors._

Yes absolutely. The thing was also only a workaround for more fundamental
issues.

But there is one important thing to notice here. The explicit diff in the
app.config file is often valuable, because that's where we can bless
things. I just wanted to point that out.

Am 05.09.2017 10:54 vorm. schrieb "Kevin Ransom (msft)" <
[email protected]>:

Yes I used a caveat, but so did you::
Of course even this is not a perfect solutions since there are still
endless ways to mess up, but practice showed that these tricks work very
effectively against common human errors.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/dotnet/standard/issues/481#issuecomment-327113818,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AADgNDd8OL3LD9bKmJvS69cZacEOZs3tks5sfQwzgaJpZM4PKtHI
.

@forki
I don't disagree with you, I know it sounds like I do, but I don't. I think the position you take, where the developer of the app is the only one who knows the right answer is a decent position to take.

I think I would take a different one though. I would suggest that the most common position is that future versions of useful assemblies will be compatible and incompatibility will be a bug in the library that will be quickly fixed, if found quickly.
I could be wrong ... but I know that we try hard to maintain compatibility and to respond quickly when we mess up.

Major releases that introduce breaking changes is a completely normal thing that happens, all the time. That's not a bug and might never be fixed.

Sigh !!!! I wish I worked in a world where I could get away with that, it must be lovely.

Sigh !!!! I wish I worked in a world where I could get away with that, it must be lovely.

In my experience, breaking changes (potentially each minor version) is the default state if the maintainers don't explicitly promise binary compat.

Sad, but realistic.


Just my two cents and a different take on the app.configs: I like to have binding redirects in the source-tree version of my app.config, because that means I can copy-paste an app.config from source control to production.

Instead I would want the build to _verify_ and _fail_ if the app.config is not compatible with the actual binary output (e.g. if the app.config contains 5.0 but the bin directory contains 10.0).

This is not possible with nuget because dependencies float and so the source tree would be modified on each restore.

But I think this also slightly shows the different philosophies between nuget and paket:

Paket tries to resolve dependencies once and then locks them. Later restores will not modify this state.

Nuget instead resolves each restore, potentially different between runs, __making reproducable builds impossible__, and then has to implement hacks like generating an app.config at build time to _hopefully_ make things run.

I've said it before, but just wanted to repeat myself: I didn't move our work solution to paket because paket is so great (well, it actually is). I moved it because nuget is so bad.

And I think that's exactly why MS position (or let's say my perception of
their position) and position of (some not so small part of) the community
differs:

1) Microsoft did a really good job in maintaining backwards compatibility
for a very long time.
2) It also synchronizes basically all releases of the whole thing to the
same day.
3) It uses very few external dependencies (Newtonsoft and xunit and the
major ones)

So many of the incompatibilities that we see day to day in the wild just
don't happen with these things. So if you only use that part of the
ecosystem (which a lot of Microsoft's internal stack does) then you can
come to the conclusion that it's not a big deal. There are only smaller
conflicts and Microsoft is usually fast to address them in whatever way.

But all I can say is: "reality is a bitch".

The ecosystem is much more messy and many maintainers of packages are just
figuring out what the latest bestest way to structure a nupkg is. And it
still changes A LOT. So A LOT of different versions are floating around
with even misspelled or made up target framework monikers. Things where
people assume .NET Standard would work as a standard but crash on mono and
and and. It's really really hard.
And whenever a user discovered an incompatibility he or she needs a way out.

Yes automatic stuff is nice, but we need to be able to review it easily and
to change it if needed. That's the important thing that the ecosystem needs
to solve. Dependencies lock files and App.config settings are two ways on
that challenge. Regarding binding redirects I would even say a poor man's
solution, but still....

Am 05.09.2017 11:12 vorm. schrieb "Kevin Ransom (msft)" <
[email protected]>:

@forki https://github.com/forki
I don't disagree with you, I know it sounds like I do, but I don't. I
think the position you take, where the developer of the app is the only one
who knows the right answer is a decent position to take.

I think I would take a different one though. I would suggest that the most
common position is that future versions of useful assemblies will be
compatible and incompatibility will be a bug in the library that will be
quickly fixed, if found quickly.
I could be wrong ... but I know that we try hard to maintain compatibility
and to respond quickly when we mess up.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/dotnet/standard/issues/481#issuecomment-327118338,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AADgNDM6TR8Z5K5pnMZRDNVMw1AfKyMAks5sfRBkgaJpZM4PKtHI
.

Binding Redirects

@forki

think about what that means. It means there are effectively no binding redirects anymore. So in some sense the feature is gone.

You're the first person I encounter who thinks of the .NET Framework exact match binding policy as a feature :-)

Would you go so far and say that all the other .NET runtimes (CoreCLR, .NET Native, Mono) are missing a feature, because they will happily bind to the version deployed by the application -- so long the version is equal to or higher than the version that is requested?

@isaacabraham

Doesn't it just mean that the redirects are calculated by the runtime to just promote all assemblies to the version that actually is being used?

Not quite. The way binding redirect works is like this: when an assembly load is requested, the binder applies policy. This includes the runtime unification table, binding redirects, publisher policy stored in the GAC, as well as the AssemblyResolveEvent (not sure about the order). This policy might change the assembly version. After the version is determined, the binder will use the probing locations to find the excact version. If no assembly in that version is found, you get the canonical FileLoadException.

The way we see the "higher version wins" policy is like this: the application can specifcy a set of probing locations. By default, this only includes the application folder. The binder will then load the highest assembly version among all probing locations that satisfies the assembly load request. Allowing for multiple probing locations allows applications with plug-ins (like VS) to coordinate the load when multiple plug-ins share an assembly (like JSON.NET). In that case, the only sensible thing is to load the highest version across all plugins because it resolves plug-in activation order issues. Of course, one could argue that the best way is to load all shared assemblies side-by-side so that each plugin gets its own copy, but that requires multiple app domains or assembly load contexts and doesn't work in all cases where types need to be exchanged.

@isaacabraham

@KevinRansom the problem is that you might still implicitly break something e.g. imagine you have two projects A and B. A depends on V1 of dep, B depends on V2. At runtime you pick V2, as it's the higher one. But V2 introduced breaking changes compared to V1 - either behavioural (different code paths), or structural (different interface, change of method signatures).

That is true but binding redirects cannot solve this issue because there is no version that will work with both A and B. The application is toast. Now, I'd argue the only sensible thing for the app is to load V2 in the hopes hat A wasn't affected by the breaking change introduced in V2.

Issues

@esentio

I'm not aware of this issue. Did you uninstall the packages first / did you migrate the contents of the packages.config file into the PackageReference elements?

@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. I'll follow up with the NuGet team to see why 3.6 wasn't pushed yet.

Maybe I'm the first person who expressed that verbally in public Microsoft
thread but yes many people use it like that. I didn't come up with it.

Am 05.09.2017 6:03 nachm. schrieb "Immo Landwerth" <[email protected]

:

Binding Redirects

@forki https://github.com/forki

think about what that means. It means there are effectively no binding
redirects anymore. So in some sense the feature is gone.

You're the first person I encounter who thinks of the .NET Framework exact
match binding policy as a feature :-)

Would you go far and say that all the other .NET runtimes (CoreCLR, .NET
Native, Mono) are missing a feature, because they will happily bind to the
version deployed by the application -- so long the version is equal to or
higher than the version that is requested?

@isaacabraham https://github.com/isaacabraham

Doesn't it just mean that the redirects are calculated by the runtime to
just promote all assemblies to the version that actually is being used?

Not quite. The way binding redirect works is like this: when an assembly
load is requested, the binder applies policy. This includes the runtime
unification table, binding redirects, publisher polict stored in the GAC,
as well as the AssemblyResolveEvent (not sure about the order). This policy
might change the assembly version. After the version is determined, the
binder will use the probing locations to find the excact version. If no
assembly in that version is found, you get the canonical FileLoadException
.

The way we see the "higher version wins" policy is like this: the
application can specifcy a set of probing locations. By default, this only
includes the application folder. The binder will then load the highest
assembly version among all probing locations that satisfies the assembly
load request. Allowing for multiple probing locations allows applications
with plug-ins (like VS) to coordinate the load when multiple plug-ins share
an assembly (like JSON.NET). In that case, the only sensible thing is to
load the highest version across all plugins because it resolves plug-in
activation order issues. Of course, one could argue that the best way is to
load all shared assemblies side-by-side so that each plugin gets its own
copy, but that requires multiple app domains or assembly load contexts and
doesn't work in all cases where types need to be exchanged.

@isaacabraham https://github.com/isaacabraham

@KevinRansom https://github.com/kevinransom the problem is that you
might still implicitly break something e.g. imagine you have two projects A
and B. A depends on V1 of dep, B depends on V2. At runtime you pick V2, as
it's the higher one. But V2 introduced breaking changes compared to V1 -
either behavioural (different code paths), or structural (different
interface, change of method signatures).

That is true but binding redirects cannot solve this issue because there
is no version that will work with both A and B. The application is toast.
Now, I'd argue the only sensible thing for the app is to load V2 in the
hopes hat A wasn't affected by the breaking change introduced in V1.
Issues

@esentio https://github.com/esentio

I'm not aware of this issue. Did you uninstall the packages first / did
you migrate the contents of the packages.config file into the
PackageReference elements?

@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.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/dotnet/standard/issues/481#issuecomment-327222970,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AADgNC_FHlAuv8eZtdKslSrqsrhh9RYwks5sfXDTgaJpZM4PKtHI
.

@terrajobst It would be great if you could explicitly clarify the requirements for a) modifying projects and b) building projects.

For example, there is no updated download for VS2013 on https://www.nuget.org/downloads, so I assume that only VS2015 and up are supported?

a) Modifying projects:
To install a .NET Standard 2.0 (or 1.6) NuGet into a project, the package manager needs to know about the mapping, so it needs an updated nuget extension. That one seems obvious.

b) building projects:
after I have installed the package into the project, all required information _should_ be inside the project file, so do I also need to update the buildserver? I would expect not.
Can I still build with VS2013 after I have installed the package using VS2015 with updated nuget extension?

It is ok if really old tool versions like VS2013 are no longer supported, but please make it explicit which scenarios do and which don't work.

@terrajobst

That is true but binding redirects cannot solve this issue because there is no version that will work with both A and B. The application is toast. Now, I'd argue the only sensible thing for the app is to load V2 in the hopes hat A wasn't affected by the breaking change introduced in V2.

Correct. But I think there are two other points to this:

  1. With explicit BRs, you can control which direction you go. Perhaps you don't want to go upwards to the highest version, but prefer to stay at the lower one.
  2. With explicit BRs, until you put the BR in, AFAIK you will immediately get a runtime error (the canonical FileLoadException that you mentioned). It's not perfect, but I'd rather have that and know as soon as it happens - at which point we can make a decision to upgrade our solution or not - rather than risk finding out two months later when my code goes live and a bug appears.

There's value in both approaches. However, my instinctive feeling is simply that this kind of silent "natural selection" of different assembly versions is going to come back to bite all of us. Perhaps I'll change my mind on this as the discussion progresses, or not :-)

@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:

  1. Publisher policy was deprecated even before we shipped V1.0 of the CLR so the scenario is essentially invalid "as designed"
  2. The tooling to add binding redirects was removed by the time Clr 2.0 was released, because they weren't actually useful now that policy was deprecated.
  3. In the intervening years app.config binding redirects have become a general purpose binding unification facility.

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

  • Depends on Library B which depends on Library D V1.2.0.0
  • Depends on Library C which depends Library D V1.1.0.0

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:

  1. Educate the ecco-system to always reference the lowest version necessary of referenced libraries.
  2. Ensure that developers quickly address compatibility bugs

The second is easier:

  1. Change the coreclr to bind to the local assembly regardless of version number. The developers job is to deploy the correct and tested dll, since the bind is not from the shared framework the version check is not really that useful, it either works or crashes the app.
    Or add binding redirects ....... No please don't do this that would make me sad

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 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 the PackageReference elements?

Oh, now I realized where I made a mistake. My steps to reproduce the issue were:

  1. Create new solution with new unit test project.
  2. Build solution.
  3. There is test method UnitTest1.TestMethod1() generated from the template. It should be visible in Test Explorer.
  4. Delete packages.config.
  5. Close VS.
  6. Edit csproj (vbproj in my case) and put <RestoreProjectStyle>PackageReference</RestoreProjectStyle> there.
  7. Open VS.
  8. Rebuild solution.
  9. There is no test method in Text Explorer anymore.

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?

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.

  • Created a new Class Library (.NET 4.7.1)
  • Converted the project to the new VS2017 style
<?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>
  • Added nugget package for NetStandard.Library v2.0.0
  • tried to build, fails
  • Manually add reference to .netstandard.dll
  • Build Succeeds

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.

See https://github.com/NuGet/Home/issues/2913

@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:

image

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:

  • Uninstall all the current packages from nuget manager ui or pmc console.
  • Then add all packages in PackageReference format in csproj file. The syntax is like this:
    <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:

  1. net461 (exact match)
  2. net45 (same framework)
  3. netstandard2.0 (not the same framework, but compatible)

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:

netstandard_2_0_0_0-referencesto-versions_0_0_0_0

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!

@mwpowellhtx I think you can write an analyzer that targets just .NET Framework rather than .NET Standard.

@jnm2 Re: analyzers, not sure what you mean by that? That would depend on how broad an audience I want to reach, wouldn't it?

@mwpowellhtx Yes. Sorry, I might have misunderstood what you were asking. .NET Standard 1.4 has worked everywhere I've cared about so far.

Having the analyzer target .NET Standard 1.4 does not mean that the project using the analyzer needs to target anything at all. The audience you care about for analyzers are the runtimes which the IDE itself is running on.

@jnm2 No worries; I'm trying to sort out what exactly ".NET Standard" means. I have a loose understanding at the moment.

@mwpowellhtx .NET Standard is a lot like Android API levels. If you target your analyzer to .NET Standard 1.4, your analyzer will be ablw to run in Visual Studio on .NET Framework and OmniSharp on .NET Core, and this is totally unrelated to what the project being _analyzed_ is targeted.

OMG! I am so confused. Neither the warning in VS nor this thread is clear on what needs to be done. I am posting my problem here in hope someone could guide me to resolve this.

First here is the warning I get when I build my solution -
Found conflicts between different versions of "System.Net.Http" that could not be resolved. These reference conflicts are listed in the build log when log verbosity is set to detailed.

Here is my project structure -
A ---direct reference----> B ------nuget reference----> C

Project C is a small class library targeting .NET Standard 2.0.
Project B is a class library targeting .NET Framework 4.6.2 and references Project C as nuget package.
Project A is Web API 2 targeting .NET Framework 4.6.2 and has direct reference to Project B.

In the Output with verbosity set to detailed I get a huge list of package conflict some of which are listed below.

1>  Encountered conflict between 'Reference:System.IO.Compression' and 'Platform:System.IO.Compression.dll'.  Choosing 'Reference:System.IO.Compression' because AssemblyVersion '4.2.0.0' is greater than '4.0.0.0'.
1>  Encountered conflict between 'Reference:System.Net.Http' and 'Platform:System.Net.Http.dll'.  Choosing 'Reference:System.Net.Http' because AssemblyVersion '4.2.0.0' is greater than '4.0.0.0'.
1>  Encountered conflict between 'Reference:System.Collections' and 'Platform:System.Collections.dll'.  Choosing 'Reference:System.Collections' because AssemblyVersion '4.0.11.0' is greater than '4.0.10.0'.
1>  Encountered conflict between 'Reference:System.Collections.Concurrent' and 'Platform:System.Collections.Concurrent.dll'.  Choosing 'Reference:System.Collections.Concurrent' because AssemblyVersion '4.0.11.0' is greater than '4.0.10.0'.

Solution I tried
Added <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> to Project B but nothing happened.
I don't want to convert to PackageReference because -

  1. A lot of other projects references Project B and from what I understand, moving to PackageReference will have cascading effect.
  2. I plan to publish Project B to nuget. That means anyone who uses it will also need to move to PackageReference.

What other solution should I try?

We are finding the whole netcore and netstandard journey a frustration more than anything else. It feels that MS is making changes without giving deep thought how it would affect existing consumers, especially those building and maintaining enterprise apps.

Make sure your root application project doesn't use packages.config but uses PackageReference for NuGet packages

Unfortunately we can't do that. For us the PackageReference approach is fundamentally broken as there are no meaningful ways of migrating packages that have install.ps1/uninstall.ps1 (https://github.com/NuGet/Home/issues/3656, https://github.com/NuGet/Home/issues/5963, https://github.com/NuGet/Home/issues/6330).

@RussKie Yes netcore has some flaws and this very issue is one of them. However it is the best that happened to .net overall for a long time. And Microsoft does care for existing customers, you can see that because full framework is still fully supported, but if you move to netcore please describe your issue generally instead of leaving generic and unhelpful rants.

Regarding the install and uninstall powershell scripts: It is a bad idea for a package manager to allow generic code execution and I’m really glad we got rid of it. It was neither cross platform nor ever supported by Paket for example. Please don’t blame Microsoft for depending on a fixed design flaw. Instead describe your use cases you solved with them and people might point you to new features that replace install.ps1

Best, a Paket contributor

@matthid just because something didn't work for you, doesn't mean other can't nor shouldn't use it.
Perhaps you missed it, the links in my post above describe our use cases.

You don't have to move to PackageReference to consume .NET Standard libraries as long as binding redirect generation is enabled (default for 4.7.2+ projects, needs to be manually enabled as described in the issue for <4.7.2 and unit test projects AFAIK).
I'm don't think the (un)install.ps1 / init.ps1 discussion is related to this .NET Standard issue (which package authors should now slowly be moving away from for multiple reasons).

@RussKie Sorry but all those issues just seem to say "we want the old feature back" (I) not "Look this is what we did with install.ps1, how can we do that in the new world" (II). But realistically please open new issues for your use cases (as in II) as this one is for the netstandard problem and not about install.ps1. Also install.ps1 afaik is still supported if you use old-style projects, but if you move to the new world please reconsider your packaging and follow good practices.

@matthid please point me kindly where exactly the issues say "we want the old feature back". Those issues about seeking guidance from respective teams for migration.
I repeat, if something didn't work for you doesn't mean others had not use for it. If you missed it - PowerShell is x-plat, and we don't really care about Packet.

@dasMulli I respectfully disagree to the point that it is not entirely unrelated, netstandard prescribes the use of PackageReference, which changes package resolution behaviors and thus requires changes to projects. When there is a chain for shared assets, such changes have a ripple effect with serious consequences...

netstandard prescribes the use of PackageReference

Well, no. It's easier but not necessary.

For your other issues: happy to chat about them, I'm reachable in the asp/.net core community slack channel http://tattoocoder.com/aspnet-slack-sign-up/

@RussKie Now I found the concrete use cases (https://github.com/NuGet/Home/issues/3656#issuecomment-390525042). For me those look complex enough to consider using a different extension point like providing your own global tool dotnet tool install which does some of the operations after installing.

Thank you very much for the pointer. We'll definitely investigate this.
/cc: @david-m-forster

On 17 July 2018 at 17:15, Matthias Dittrich notifications@github.com
wrote:

@RussKie https://github.com/RussKie Now I found the concrete use cases (NuGet/Home#3656
(comment)
https://github.com/NuGet/Home/issues/3656#issuecomment-390525042). For
me those look complex enough to consider using a different extension point
like providing your own global tool dotnet tool install
https://github.com/dotnet/docs/blob/master/docs/core/tools/global-tools.md
which does some of the operations after installing.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/dotnet/standard/issues/481#issuecomment-405483543,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AEMyXq0zM1wrrmsJrWGFmcMHx_hoHCMrks5uHY8CgaJpZM4PKtHI
.

@ankitbko I know this is late, but: I eventually got down to referencing System.Net.Http in your "Project B" and including the needed System.Net.Http dll in the nuget package I packed for "Project A" to consume.

@daghb Great! How did you do it?

@ankitbko

Supply your "Project B" with a nuspec file, and in addition to your own DLL, also include the System.Net.Http.dll lin the files section:

  <files>
    <file src="bin\release\net462\MyDll.*" target="lib\net462"/>
    <file src="bin\release\net462\System.Net.Http.*" target="lib\net462"/>
    <....>
  </files>

Pack the file using nuget and refer to the .nupkg file in your "Project A".

If you need any further elaboration, I can contact you using the email address on your github profile - just give me a hint here.

@daghb No, you do not want to include a "system" reference in the <files/>. That's not the way to do that. If you have a dependency on System.Net.Http anything, then you want to include that as a first class reference; there's a special section for that. I'm 99% certain that NuGet will do the right thing and locate the reference for you (untested). Any any other hard System reference.

@mwpowellhtx I know, but after a year of troubling with these System.Net.Http issues and no viable solution except for this one, even the bravest give up. I can confirm I have at least experienced 20 or so different use cases where this solution is just one of them. Each minor version of Visual Studio or MSBuild brings up a number of new issues related to this issue.

@daghb Admittedly, I have not been dealing with the Http stacks that intimately, per se. However, having followed the Core/Standard trajectory somewhat, I'm fairly certain that the HTTP, MVC, WebApi, etc, issues are at least some of the motivating factors, which explains a lot of the breaks, IMO.

But even that is tangential, at best, to the issue here, I think.

I found the same-ish issue to be the case when I wrote some unit tests to build projects using the Roslyn compiler diagnostics, developing some analytics at the time. If memory serves, my workaround was to invoke a NuGet Restore as a separate step, which seemed to have resolved the issue(s).

That being said, I was under the impression that these were supposed to be automatic steps in the process, or perhaps I was bypassing the MSBuild, which would have otherwise invoked said steps, but I could be mistaken there.

@mwpowellhtx

Thanks for your sympathy. Actually, as I live within "dll hell" trying to cater for lots of different configurations with .NET 4.5.1/x86 (due to 3rd party libraries), .NET 4.6.2/AnyCPU due to not being able to move to 4.7.2 yet and with netstandard2.0 life is confusing enough if the tooling doesn't chop the wheel from the wheelbarrow. From time to time you have to do these occasional shortcuts.

@daghb I finally decided that with the libraries I subscribe to increasingly moving away from "DLL hell" toward Core/Standard, it was time for me to do so as well, for these very myriad reasons. I bumped into a couple of those that were impassable, so it was just simply time to do so. I'd encourage you to consider the same. In my decision making process, I considered Core, but thought that Standard was the better choice to target. So far so good, fingers crossed, and these assets integrate fairly well thus far with 4.7.x runtime targets, Core targets, etc.

Anyway, it's a bit o/t from the OP.

@daghb I didn't wanted to pack "Project B" into nuget as "Project A" is quite dependent on it and I loose the debugging experience if I do it. Plus the issue was not just with System.Net.Http but with almost all the System." libraries, which meant I will have to pack all of them.

I gave up on this long time ago. Luckily for me "Project C" was our in-house developed package and the simplest and most efficient solution at the moment was to recompile and pack it targeting full framework.

In any case, thanks for the workaround. Will definitely help if I face this in future. Also once I get bandwidth, will revisit my "Project A" and try this to see how it works.

Now a days I just follow simple rule - Either its netstandard (and PackageReference) all the way or not at all. Mixing it with full framework carries with it the problems I would rather avoid in my life.

@ankitbko And to these points, yes, as far as I know, "testing" or "debugging" project dependencies is a separate concern from packaging. You can make the project reference, however, the packaging is a separate concern, again, as far as I know. In so doing, you do need to be careful the versions are all aligned correctly when you approach packaging.

Yes, netstandard is the way to go, until the very point when you need to hit whatever runtime. Best to leave it targeting netstandard until the very last moment.

I have a new 4.7.2 windows service accessing a .NET Standard 2.0 library project - none of its dependencies are being copied over (Dapper, FluentSMTP). So this issue appears to still be a problem. The flag AutoGenerateBindingRedirects is set to true in the service. Any other ideas?

I try to install the Zxing.netfrom NuGet and the same error pops up I dont wan to change to .NetFramework is there an other way to add the library to my project?

Install-Package : Could not install package 'ZXing.Net 0.16.4'. You are trying to install this package into a project that targets '.NETFramework,Version=v3.5,Profile=Unity Full v3.5', but the package does not
contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.
At line:1 char:1

  • Install-Package ZXing.Net -Version 0.16.4
  • ~~~~~~~~~

    • CategoryInfo : NotSpecified: (:) [Install-Package], Exception

    • FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand

@Zetrq Judging from the error message, it seems that you are using .NET Framework 3.5 which is not compatible to netstandard (not even 1.0). So whatever your issue is is not really related to this issue.

According to the NuGet information for ZXing.Net, it does support 3.5 (unrelated to its netstandard support), so it should work. But it might be that Unity does not support it properly like that. Not sure about that since I haven’t used 3.5 in ages.


@nhustak Hard to tell what’s going on there but in general, there is nothing in a .NET Framework 4.7 project that would prevent you from using a netstandard library. During build, its dependencies should be carried over properly. Is your framework project a NET.SDK project? Are you using package references or packages.config? Can you share your csproj?

So am I correct in saying that when referencing a .NET standard 2.0 project from a .NET 4.7.2 web project - I need to add all external dependencies (e.g. NuGet packages) that the .NET standard project contains to my web project too?

As already touched on - this is quite horrible for development teams attempting to shift enterprise solutions to use .NET standard/core.

Our strategy so far has been shifting class libraries from .NET framework to .NET standard - but when doing this we are faced with issues of our Web / Console applications failing to resolve these external dependencies.

It is an ugly fix to have to manually add all dependencies from an imported project to the project doing the importing. Especially as it will be all to easy for someone to look at these "unnecessary" references in the future and remove them - potentially leading to runtime errors in production code down the track.

Our team (myself included) thought the introduction of .NET 2.0 meant that things were finally ready for us to start the shift - but the experience has so far left us feeling less confident than before.

@nzandy No, that’s just not correct. You can consume netstandard libraries from any framework that implements netstandard itself. So you can consume it directly from both .NET Core and .NET Framework.

Dependencies are transitive, so there’s no need to add dependencies multiple times. If you see that happening to you, then you are doing something wrong.

@nzandy are you using <PackageReference> in your net472 projects?

@poke My understanding is, this is partially accurate. From what I understand there are some constraints, netstandard1.x -> net46x, netstandard2.x -> net47x, and so on. The devil is in the fine print. Otherwise, sure; just be sure to RTFM.

In the scenario described by @nzandy what is the solution when we can't update the web project to use <PackageReference> ? We can't switch to using it because we are using nuget packages that make use of the content folder which is currently not supported using the <PackageReference> style, https://docs.microsoft.com/en-us/nuget/reference/migrate-packages-config-to-package-reference#package-compatibility-issues

We have a .Net Standard v2.0 project that uses .Net Standard v2.0 nuget packages, when we reference this project from the Web Framework 4.7.2 project we get the missing dll issue, as I said above we can't switch it to use <PackageReference> as we have unsupported nuget packages we are using, is the only option to make our .Net Standard v2.0 project multi-target, targeting both .NetStandard 2.0 and Framework 4.7.2?

@MatthewRudolph the only workaround is to manually add all the dependencies from net standard library to web project which is packages.config based. There has been no change in packages.config behavior so it still doesn't get transitive dependencies.

Although we've some workitems in our backlog to fix some of these packages compatibility issues so that existing packages which works with packages.config, can also work with PackageReference without any explicit update. One such issue is how to make content folder usable with PackageReference.

For others reference, we (@MatthewRudolph ) and myself have chosen to follow a different strategy after doing more research. We have changed our .NET standard projects to be multi targeted. This was suggested here: https://github.com/Microsoft/msbuild/issues/1582#issuecomment-311019209

This means that .NET framework projects consuming our class library will get the packages, without having to change all of these to (and we also had projects that couldn't do this because they had scripts around the packages - this would require these projects to have the transitive dependencies added explicitly to the consuming project).

This wasn't an ideal solution... but it now means that we can reuse these multi targeted projects between both .NET core applications and .NET framework applications.

If anyone has questions / concerns to alert us about using this approach please feel free to respond!

I encounter this issue which seems related to this. But the migration is not available for asp.net project.

Even using this trick:

  • Open the csproj
  • Replace the ProjectGuid by {7C796B6B-86B5-4C57-ADAA-12CF1FECDA71} and remove ProjectTypeGuids
  • Now right click on reference, you should be able to migrate
  • Put back the previous ProjectType and ProjectTypeGuids

I get warnings, that I'm not sure I'm comfortable with:

Microsoft.CodeAnalysis.Analyzers           v2.6.1install.ps1 script will be ignored when the package is installed after the migration.
--
  | Microsoft.CodeDom.Providers.DotNetCompilerPlatform           v2.0.0install.ps1 script will be ignored when the package is installed after the migration.'content' assets will not be available when the package is installed after the migration.XDT transform file 'content\net45\app.config.install.xdt' will not be applied when the package is installed after the migration.XDT transform file 'content\net45\app.config.uninstall.xdt' will not be applied when the package is installed after the migration.XDT transform file 'content\net45\web.config.install.xdt' will not be applied when the package is installed after the migration.XDT transform file 'content\net45\web.config.uninstall.xdt' will not be applied when the package is installed after the migration.XDT transform file 'content\net46\app.config.install.xdt' will not be applied when the package is installed after the migration.XDT transform file 'content\net46\app.config.uninstall.xdt' will not be applied when the package is installed after the migration.XDT transform file 'content\net46\web.config.install.xdt' will not be applied when the package is installed after the migration.XDT transform file 'content\net46\web.config.uninstall.xdt' will not be applied when the package is installed after the migration.

Adding +1's to this issue appears to be no impact.

I've also encountered this, and tried all of the extensive advice in this thread to migrate a 4.6 ASP.Net project to 4.7.2... and it doesn't work.

After migrating to PackageReferences and updating my bindings by hand, I still encounter the dreaded System.IO.FileNotFound error at runtime for System.Web.Http.

As far as I can tell, the summary of this entire thread basically boils down to:

There is currently no migration path from < 4.6.1 to > 4.6.1 for ASP.NET projects.

No migration tooling for ASP.Net projects, and the guidance by doing it by hand (as shown by the dozens of issues referenced in this thread), don't work.

That's it. End of story.

This is extremely disappointing, and should be much more clearly communicated; because the migration advice for 4.7.x doesn't mention anywhere that this is the case.

@shadowmint In case it helps you, I have looked up how we dealt with this last year. After moving to _PackageReference_, we had to add a binding redirect to App.config that points to 4.0.0.0:

  <dependentAssembly>
    <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
    <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.0.0.0"/>
  </dependentAssembly>

_Only_ by pointing it to 4.0.0.0 I could get it working. My suspicion is that this has something to do with the GAC, where this version is found and somehow preferred.

@shadowmint I don't think asp.net (classic) projects support PackageReference yet.
In any case, you should see a warning in the error list about binding redirects. you should be able to double click that and VS will add the missing binding redirects to your web.config file.

you should be able to double click that and VS will add the missing binding redirects to your web.config file...

You most certainly can click on the warning, and have visual studio update your web.config.

If you want it to actually do something meaningful, you should first go in and remove any existing bindings, because you probably have some which are invalid or unnecessary, and it won't update them correctly.

However, even so, unfortunately, after doing so you may encounter:

Could not load file or assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

Despite having this in your web.config have no reference to System.Runtime after using the visual studio helper function.

What then?

I mean, I think it's fair to say from the length of this thread, and that people are still linking new issues to it, that this is fundamentally broken.

...and look, sure. I appreciate that it's not always easy to upgrade, and it's not always easy to support legacy projects, and building tooling to automate processes takes time and effort.

What is not ok is pretending that this is just a little bug you can sweep under the carpet, like oh hey, we're going to release 4.8 in a few months, upgrade everyone... when for two years:

  • it's been a nightmare to upgrade to the most recent releases for people,
  • people still can't upgrade framework version.
  • the 'suggested' solutions are either a) if you're a library author multi-target your library so it doesn't target net standard, and b) if you're an application author, manually edit your configuration files, use the VS tooling and good luck with that when it doesn't work.

Let's face it: You cannot upgrade some projects at this point.

That's it.

Now, if someone had pinned that to the top of this thread, I wouldn't have wasted a week trying to upgrade my projects; perhaps, by leaving this here, I can help the next person not doing the same.

I'm tracking related issues and information in a list. They are related to System.Net.Http, System.Runtime, System.IO, System.ValueTuple, System.Buffers and others.

https://github.com/dotnet/corefx/issues/32587
https://github.com/dotnet/corefx/issues/32561
https://github.com/dotnet/standard/issues/481
https://github.com/dotnet/standard/issues/567
https://github.com/dotnet/standard/issues/558
https://github.com/dotnet/standard/issues/887
https://github.com/dotnet/standard/issues/891
https://github.com/dotnet/corefx/issues/32610
https://github.com/dotnet/corefx/issues/30642
https://github.com/dotnet/corefx/issues/32757
https://github.com/dotnet/standard/issues/895
https://github.com/dotnet/standard/issues/877
https://github.com/dotnet/standard/issues/521
https://github.com/dotnet/standard/issues/295
https://github.com/dotnet/standard/issues/476
https://github.com/dotnet/standard/issues/184
https://github.com/dotnet/standard/issues/936
https://github.com/dotnet/standard/issues/941
https://github.com/dotnet/corefx/issues/33148
https://github.com/NuGet/Home/issues/7440
https://github.com/dotnet/corefx/issues/31532
https://github.com/dotnet/corefx/issues/22781
https://github.com/dotnet/corefx/issues/23306
https://github.com/dotnet/corefx/issues/29622
https://github.com/dotnet/corefx/issues/9846
https://github.com/dotnet/corefx/issues/17522
https://github.com/dotnet/corefx/issues/25773

All of these have the same very few underlying issues.

.NET 4.7.2 helps with some but not all of these. You can look at my comments on some of these issues for some ideas on how to work around those problems. I also have a central list of ideas to try.

@GSPP a bit cheeky of me, but is there any chance of a TLDR?

@cocowalla I think there are multiple issues none of which I fully understand. What I did was to experiment a lot, diff the changes in detailed MSBuild logs and draw some conclusions.

I encountered these issues in multiple projects. It is very easy to trigger them (e.g. new solution, add DLL project, add two NuGet packages, bug). Google and this issue tracker is full of people hitting this. I spent days with this.

These are candidates for workarounds:

  • Upgrade to .NET 4.7.2 (fixes some but not all issues)
  • Downgrade to .NET 4.7.0. This might actually help because the problems started in .NET 4.7.1 when netstandard was partly integrated into the Framework. I have not tried downgrading and it might not be feasible on Windows 10.
  • Update all packages (doesn't help much)
  • Reinstall all packages (I found that "Update-Package -Reinstall" was not enough. Each package must be reinstalled individually ("Update-Package -Reinstall PackageName") and in each project).
  • PackageReference seems to solve some issues but I encountered show-stopper bugs
  • Delete binding redirects for those assemblies that can not be loaded (e.g. System.Runtime)
  • Change the binding redirect to the framework version (e.g. System.Runtime to 4.0.0.0)
  • I encountered build errors when a dependent project mysteriously referenced a different version of an assembly although everything clearly specified the right version. Manually play with the <Reference> elements in the csproj
  • Add references that appear unneeded (I fixed a System.Buffers problem that way)
  • Delete bin/obj folders (this often makes a difference because old assemblies are left there. VS clean does not remove them! This can make you believe that your solution works but it really just depends on old assemblies. I always have deleted these folders between tests to be sure.) See this related issue for an example of how simply starting VS can put bad DLLs into bin. Therefore, you need to clear bin after starting VS.
  • If you want to know what an assembly resolves to use the VS properties panel on the reference. This uses the information from MSBuild. Note, that each project might resolve each reference differently.
  • Use fuslogvw.exe settings to turn on assembly load information and see what's loaded.
  • Use Sysinternals Process Monitor to see what file paths are being search for the DLL name by the CLR and by MSBuild.
  • Note, that MSBuild can use other assembly versions and locations against your direct instructions in the csproj. Both version and hint path can be overridden by a process that I do not understand. There is no way to truly force anything.
  • The "Automatic binding redirects" feature can make a difference.
  • I have only worked on .NET Framework projects. For .NET Core and netstandard there might be differences in behavior. Some of the issues from my list are about netstandard.

As you can see this is a dirty situation. Be happy when you find a working state, check it into source control and risk no further changes :)

I understand the .NET team is aware and working on a fix. I am puzzled, though, how such egregious issues can be left standing for such a long time. 4.7.2 is 6 month old and these bugs are older.

I would like to add here, that the suggestion that this is because "users are not on 4.7.2 or using the latest VS" is not correct (see #895 for a minimal repo that flatly contradicts this assertion).

The issue here, is that this issue isn't being looked after.

Although, potentially, the issues linked here by @GSPP may or may not all be exactly the same issue, it is extremely difficult to get any kind of 'tldr' on this issue, or have any idea what to do when you encounter it on any of the related issues.

The pinned advice here is simply:

  • Upgrade to 4.7.?
  • Upgrade to PackageReference
  • Update bindings / use autobindings tooling from VS (whatever internal magic that uses)

...that's it. The reason we're forced to trawl stack overflow and these issue trackers for other crazy things to try (I mean seriously, go and read #891, #895), if that we have zero guidance here on what to do when the above doesn't work.

  • Where should repo's be posted?
  • Who is looking after them?
  • What is being done to fix the root cause?
  • What meaningful things should be tried to resolve these errors?

This thread epitomizes the problem:

Look, what you should be doing is locking and closing all the related issues and all the related issue trackers and directing people to "try [list of suggestions from ?? here], and post a repo of the issue [on this issue tracker] which uses [this issue template for a repo] if that doesn't help you".

Just leaving these issues open isn't achieving anything; the only thing @GSPP appears to have actually done here is raise the profile of this issue significantly enough that someone has actually decided they need to respond to it finally.

That it took someone manually going out and linking all these issues for that to happen is massively disappointing; surely there is more going on 'behind the scenes' here, but it's certainly not visible to us.

Some of the fixes suggested may work, some may not... but this is the most pertinent part of the above response:

As you can see this is a dirty situation. Be happy when you find a working state, check it into source control and risk no further changes :)

Just a quick note: I got this on a brand new ASP.net website (Open>Website in Visual Studio 15.8.7) when I installed a NuGet package targeting .NET Standard 2.0. The website is already targeting 4.7 (the server doesn't yet support 4.7.2, so that's not an option). When I try to have Visual Studio fix it for me, I get the error 'CSharpAddMissingReferenceCodeFixProvider' encountered an error and has been disabled.

Clicking Show Stack Trace gives this output:

System.AggregateException : One or more errors occurred. ---> Unable to cast COM object of type 'System.__ComObject' to interface type 'VSLangProj.VSProject'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{2CFB826F-F6BF-480D-A546-95A0381CC411}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedAction.InvokeWorker(Func`1 getFromDocument,IProgressTracker progressTracker,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedAction.<>c__DisplayClass18_0.<InvokeCore>b__0()
   at Microsoft.CodeAnalysis.Extensions.IExtensionManagerExtensions.PerformAction(IExtensionManager extensionManager,Object extension,Action action)
---> (Inner Exception #0) System.InvalidCastException : Unable to cast COM object of type 'System.__ComObject' to interface type 'VSLangProj.VSProject'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{2CFB826F-F6BF-480D-A546-95A0381CC411}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
   at Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.VisualStudioWorkspaceImpl.TryAddReferenceToProject(ProjectId projectId,String assemblyName)
   at Microsoft.VisualStudio.LanguageServices.Implementation.VisualStudioAddMetadataReferenceCodeActionOperationFactoryWorkspaceService.AddMetadataReferenceOperation.Apply(Workspace workspace,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CodeActions.CodeActionOperation.TryApply(Workspace workspace,IProgressTracker progressTracker,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Editor.Implementation.CodeActions.CodeActionEditHandlerService.ProcessOperations(Workspace workspace,ImmutableArray`1 operations,IProgressTracker progressTracker,CancellationToken cancellationToken)
   at async Microsoft.CodeAnalysis.Editor.Implementation.CodeActions.CodeActionEditHandlerService.ApplyAsync(<Unknown Parameters>)<---

I was able to update the web.config manually in system.web/compilation/assemblies to add: <add assembly="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51"/> manually and that fixed the issue. I'll be opening this issue for the Visual Studio team as well because of the error. But this clearly has yet to be resolved.

Re: @shadowmint comments, I agree, and unless someone can argue otherwise, yes, I am intending to still target desktop framework in some scenarios, net472, etc. I've also bumped into test issues around x64 not being fully supported via xunit and Test Explorer. At the moment working around those by testing in a netcoreapp assembly; however, I'd like to be targeting net472. Apologies if that's a bit OT; if there's a better repo for me to follow that up on, would be appreciated. Thanks!

I don't want to know how many hours I've spent on this. I've converted all the projects in the sln to PackageReference. The things that boggles my mind is I can always build in VS but never with msbuild, even with wiping bin/obj.

Wow, this is so hideously bad and still broken years later? I now remember why I looked at the 4.7.2 upgrade and bounced off it. Now I am forced to by other packages.

It's pretty clear that MS is focusing on .NET core only and letting everything else hang out to dry. VS 2017 will no longer be updated even though Razor support is now very poor and slow... the promised "soon" fixes never came: https://blogs.msdn.microsoft.com/visualstudio/2018/10/05/visual-studio-2017-and-visual-studio-for-mac-support-updates/#comment-307125

/end rant

Here's what fixed this issue for me:

1) Set a bindingRedirect in the app.config from 4.2.0.0 back to 4.0.0.0:

      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>

2) Disable auto generating binding redirects by adding this in the first in every .csproj:

<AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>

That AutoGenerateBindingRedirects setting is what makes this so insidiously broken. You can fix the project references or bindingRedirects all you want, but if you have AutoGenerateBindingRedirects still enabled, it'll go in and create a busted bindingRedirect with newVersion="4.2.0.0" that breaks everything all over again.

You've got to have both (1) and (2) together or you end up chasing your tail for hours.

A year has passed. As before.

Despite using PackageReference and auto-binding-redirect, this broke for me when I installed donet core sdk "2.2.200-preview-009648", which includes a preview of msbuild 16. Uninstalling that sdk (which reverted the default build engine to "15.9.20+g88f5fadfbe for .NET Core") solved the issue, this time at least, on one machine.

I have hit this issue once again.

My legacy 4.7.2 Unit Test project now references a .NET standard library

When I run the test - runtime error Could not load file or assembly 'Microsoft.Extensions.Configuration.Abstractions

The .NET standard library references that nuget package. But the DLLs do not get pulled through to my .NET 4.7.2 tests project bin folder.

This is before my tests project uses packages.json, and I cannot convert it to PackageReference style - because my test project has dependencies that use the "content" folder that is not supported by PackageReference.

Looks like my only option is to manually reference these transitive dependencies from my unit test project.

Even though I had hit this issue around 6 months ago, still took me a long time to reach this same conclusion - I feel sorry for the people that are hitting this issue for the first time!

It needs to be made clearer to developers that there are some real issues if people want to work with solutions containing both .net standard and .net framework projects.

@whomeveritmayconcernatmicrosoft If you're not going to fix the problem at hand, at least lower people's expectations by stating .NET Standard and Core are completely incompatible with .NET 4.6.1 and old style projects of ANY .NET version.

Cheers.

Had similar issue on net472 application:
Could not load file or assembly 'System.Runtime, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
evaluating Environment.StackTrace.

Occurs only after deployment (MSI installer). Running from Visual Studio no problem.
Application consists of 50 projects across approx. 10 solutions. Approximately 40% on .netstandard 2.0 and net472. Rest only net472.

Solved as follows:

  • Removed all existing bin, obj and some site-specific deployment folders.
  • Check all app.config for listing the right SKU. Several still pointed to 4.5 and 4.7.
  • All csproj were already switched to PackageReference and often VS2017 project format.
  • Everywhere enable auto generate bindings (yes, set to true, not to false) in csproj files.
  • Remove all existing assembly bindings from app.config files.
  • Build all solutions in right order, each one delivering a nuget package as input for others.
  • No assembly bindings were added, besides one on the setup projects and newtonsoft.json.
  • Programs deployed fine without errors.

Occurs only after deployment (MSI installer). Running from Visual Studio no problem.

I think if you were to delete the bin folder in the project throwing the error, you would get the same issue running locally via Visual Studio

@nzandy Yes, that was my initial expectation too, but no luck. The app.config plus magic of VS created another PROGRAM.config. Run from output folder or VS worked. Deploying it (with some Wix magic and obfuscation to create a msi) led to a failing program. Manually adapting the PROGRAM.config was a workaround; removing system.runtime fixed it after deployment.

Has anybody replacing the problematic csproj by one created as follows: create a .NET Core project, edit it as text, and change netcoreapp2.1 to net471 or whichever version you need.

This is my preferred way in general of creating Framework projects, as you get the clean, new layout: class includes are implicit and you can edit the csproj as text while it is still loaded.

I am wondering if it helps with the package issues (using PackageReference, naturally).

@Timovzl yes, I always do this (and use PackageRef) - same issue with binding redirect hell if you're stuck on net461 though. Also, some projects can't move to the new csproj format, for example ASP.NET MVC 5 projects (which aren't supported with csproj)

I tried adding GenerateBindingRedirectsOutputType to my unit test project but it didn't help.

An exception occurred while invoking executor 'executor://nunit3testexecutor/': Exception has been thrown by the target of an invocation.
Could not load file or assembly 'System.Runtime.Loader, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

See also
https://github.com/dotnet/corefx/issues/22142

The tests run and pass fine locally.

Closing as this an announcement. For the record, we've started to track issues related to .NET Framework support with this label.

Could you please make this part _idiot proof_?

  1. Make sure your root application project doesn't use packages.config but uses PackageReference for NuGet packages
    o If you currently don't have packages.config, simply add <RestoreProjectStyle>PackageReference</RestoreProjectStyle> to your project file
    o If you currently do have a packages.config, convert the contents to packages references in the project file. The syntax is like this:
    <PackageReference Include="package-id" Version="package-version" />

I am new to .Net and I already screwed my project to the point of having to start all over –all my bad obviously– trying to fix this issue. So I don't want to have to do it again just because I'm _figuring out_ what to touch in which file. Neither my boss wants.

What I'd like to know is:

  • Do I have to _convert the contents_ in my csproj files?
  • This _PackageReference_ tag, where do I have to place it? What does it substitute?
  • Where do I get _package-id_ and _package-version_ from? Is it one entry for each one in my packages.config file. In that case the reference to System.Net.Http that is bothering me is not even there.

Thanks in advance,

Héctor

This might help you get some context: https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference

Basically what you want is this, if in Visual Studio you see something similar to the following:

image

Then you have NuGet package dependencies, and you are using the legacy packages.config technology. The link I provided starting this comment will tell you how to migrate (which is basically rightclicking this file and telling VS to do the migration for you)

If that is not the case, and you edit your .csproj file and see something like this:

image

Then you also have NuGet package dependencies, but you are already using the new technology (meaning PackageReference) so there is nothing left for you to do 👍

Finally, if you didn't see a packages.config, and you also couldn't find the tag PackageReference in your .csproj, then that means that you don't have NuGet dependencies, but you may have project dependencies which might have package dependencies, so you should add a property to your project to ensure that this happens. In order to do that, go to your .csproj again, and add this code immediatly after the first import on your project:
image

After doing this, make sure that from the developer command prompt you call at least once the following command msbuild yourProject.csproj /t:Restore in order to make sure that we calculate all package dependencies for you.

Let me know if you hit any problems after following that.

Thanks @joperezr I really appreciate

I can't get an older project that worked fine to work again, I still get the exception regardless of anything I've tried. I may just convert this from a .net Console app to .Net Core console and be done with it.

Was this page helpful?
0 / 5 - 0 ratings