Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.NET Standard issues on .NET Framework 4.7.1 #567

Closed
AlexGhiondea opened this issue Oct 31, 2017 · 59 comments

Comments

Projects
None yet
@AlexGhiondea
Copy link
Member

commented Oct 31, 2017

Summary

Applications that target the .NET Framework 4.6.1 and use .NET Standard libraries may experience System.TypeLoadException exceptions when running on the .NET Framework 4.7.1

Symptoms and root cause

The .NET Framework 4.7.1 adds support for .NET Standard in-box. As part of this change, a few assemblies that used to ship independently from the .NET Framework have now been added to the .NET Framework. As these .NET Standard assemblies were not part of the .NET Framework prior to .NET 4.7.1, they were deployed with the application, and a binding redirect was added to the application's app.config file.

When running on the .NET Framework 4.7.1, where the assemblies are now part of the Framework, the application now has two types with different identities, and that leads to a TypeLoadException. One type comes from the app-local assembly, and the other one comes from the .NET Framework assembly.

Also reported here: microsoft/dotnet-framework-early-access#9

The following types are potentially impacted by this issue.

  • System.Data.Common.DbColumn
  • System.Data.Common.DbDataReaderExtensions
  • System.Data.Common.IDbColumnSchemaGenerator
  • System.Diagnostics.StackFrameExtensions
  • System.Globalization.GlobalizationExtensions
  • System.Net.Sockets.SocketReceiveFromResult
  • System.Net.Sockets.SocketReceiveMessageFromResult
  • System.Net.Sockets.SocketTaskExtensions
  • System.Runtime.CompilerServices.TupleElementNamesAttribute
  • System.Runtime.InteropServices.Architecture
  • System.Runtime.InteropServices.OSPlatform
  • System.Runtime.InteropServices.RuntimeInformation
  • System.Runtime.Serialization.DataContractSerializerExtensions
  • System.Runtime.Serialization.ISerializationSurrogateProvider
  • System.Security.Cryptography.ECCurve
  • System.Security.Cryptography.ECParameters
  • System.Security.Cryptography.ECPoint
  • System.Security.Cryptography.IncrementalHash
  • System.Security.SecureStringMarshal
  • System.StringNormalizationExtensions
  • System.Threading.PreAllocatedOverlapped
  • System.Threading.ThreadPoolBoundHandle
  • System.TupleExtensions
  • System.ValueTuple
  • System.ValueTuple`1
  • System.ValueTuple`2
  • System.ValueTuple`3
  • System.ValueTuple`4
  • System.ValueTuple`5
  • System.ValueTuple`6
  • System.ValueTuple`7
  • System.ValueTuple`8
  • System.Xml.XPath.XDocumentExtensions

Plan

We have identified the problem and we will ship a fix for .NET Framework 4.7.1 in the next few months and in the next version of .NET Framework.

Workarounds

There are two ways to work around this issue:

  • When running on .NET Framework 4.7.1, remove the binding redirects from the app.config file for the assemblies that are now part of the .NET Framework.
  • Re-target your application to target the .NET Framwork 4.7 or .NET Framework 4.7.1.
@leastprivilege

This comment has been minimized.

Copy link

commented Nov 1, 2017

Re-target your application to target the .NET Framwork 4.7 or .NET Framework 4.7.1.

What does that mean for library authors?

@leastprivilege

This comment has been minimized.

Copy link

commented Nov 2, 2017

OK - since no-one cares to answer - maybe I need to elaborate.

We have reports that applications using our libraries have the problem described here. See links above.

Can we as a library author do anything to prevent these problems - or is that the problem of the application? Shall we e.g. at least for the time being add a net471 target that uses the framework references instead of nugets?

Or will you just fix that issue (hopefully not in a couple of months - but earlier) and we'll just forget about 4.71...?

@sharwell

This comment has been minimized.

Copy link
Member

commented Nov 3, 2017

@leastprivilege I expect you will get an answer sooner rather than later. I'm trying to learn more about exactly what steps a user takes to enter this scenario, since it seems to affect some users with .NET 4.7.1
but not others.

@AlexGhiondea

This comment has been minimized.

Copy link
Member Author

commented Nov 3, 2017

@leastprivilege, @sharwell I understand your concerns. Here is more information about what is happening.

The scenario that is broken is the following:
An application that targets .NET Framework 4.6.1 and references a .NET Standard 2.0 library.
In addition to that, the application needs to also directly reference System.ValueTuple library (or any of the assemblies that contain the types listed above) and have a binding redirect for that version of the library.
In addition to that, the application needs to exchange the System.ValueTuple type (or of one of the types above) with the library. There are many ways this can happen (pass an instance of a type between the two, implement an interface that uses System.ValueTuple in the signature, etc).

When running on .NET Framework 4.6.1 the application will use the System.ValueTuple assembly that ships with the application (since System.ValueTuple is not part of the .NET Framework). The library also uses the System.ValueTuple type that ships with the application because the netstandard.dll that ships with the application will type-forward to the System.ValueTuple contract.

When running on .NET Framework 4.7.1. the application will use the System.ValueTuple assembly that ships with the application. This is because the application has a binding redirect to the explicit version of System.ValueTuple that comes with the application.
The library will end up using the System.ValueTuple type that comes from .NET Framework 4.7.1. The reason for this is that the library will load the netstandard.dll from the GAC (since now netstandard.dll is part of the framework) which type-forwards directly to the implementation in .NET Framework 4.7.1.

When the 2 (application and library) exchange an instance of System.ValueTuple you will end up with 2 different identities for a single type (i.e the types don't unify) which causes an exception.

We are planning to fix this by changing the way netstandard.dll's type-forwards are generated. Instead of directly going to the implementation, they are going to type-forward to the contracts for the types that used to ship in separate packages and are now in the .NET Framework.

@leastprivilege adding a net461 asset is going to be the fastest way for you to unblock your customers. If you also have a netstandard 2.0 asset then you will ensure that the code remains compatible with .NET Standard and that it can run on 4.6.1

@leastprivilege

This comment has been minimized.

Copy link

commented Nov 3, 2017

Thanks for the clarification - does this look right to you:

https://www.nuget.org/packages/IdentityModel/2.15.0-preview1

@Tornhoof

This comment has been minimized.

Copy link

commented Nov 3, 2017

May I suggest a consolidated post on all the issues currently with .NET Standard and the relevant netfx frameworks?
I see that you tag your posts as announcement, but a consolidated view would be nice and put it somewhere visible, e.g. the dotnet blog or even that shiny purple dot.net website.

@Kieranties

This comment has been minimized.

Copy link

commented Nov 3, 2017

@AlexGhiondea I assume this issue would also be apparent for applications targeting net462 and consuming netstandard2.0 libs in a net471 environment?

@sharwell

This comment has been minimized.

Copy link
Member

commented Nov 3, 2017

@AlexGhiondea I have an application which, as far as I can tell, falls exactly into the set of impacted applications. For the majority of users, the scenario is not causing problems. However, in a small subset of cases the users are experiencing problems.

The case we are hitting involves IncrementalHash:

System.Security.Cryptography.Algorithms System.Core Result
4.7.2556.0 4.7.2556.0 Works
4.7.2556.0 4.7.2102.0 Fails

We don't know how a user can enter the latter case, where one library is updated but the other is not.

@joperezr

This comment has been minimized.

Copy link
Member

commented Nov 3, 2017

@sharwell yes, System.Security.Cryptography.IncrementalHash also belongs to the same bucket than System.ValueTuple (implementation used to live in a nuget package, but is now inbox on netfx) so most likely you are hitting the same exact issue and will be fixed with the proposed fix by @AlexGhiondea of building the netstandard facade such that it types forwards to contracts first when possible.

@sharwell

This comment has been minimized.

Copy link
Member

commented Nov 3, 2017

@joperezr The strange thing to me is I'm not hitting the described problem. The original description and follow-up describe a scenario in which this problem will occur. However, the description is current incomplete as many users who meet these conditions do not experience the described problem.

@AlexGhiondea

This comment has been minimized.

Copy link
Member Author

commented Nov 3, 2017

@sharwell I would like to know more about the environment that is happening in.

Because of the different versions of System.Core you might be in a strage case where the facade (System.Security,Cryptography) has a type-forward to the IncrementalHash type but that type is not in the System.Core.dll you have.

Do you have a repro of this case?

@AlexGhiondea

This comment has been minimized.

Copy link
Member Author

commented Nov 3, 2017

@leastprivilege the package you pointed at looks ok to me.

@tstojecki

This comment has been minimized.

Copy link

commented Nov 8, 2017

@AlexGhiondea can you give us an idea for what else might be missing? I just tried @leastprivilege package (2.15.0) which has been compiled with that extra net461 target and the dependent packages -
see the screenshot I posted here IdentityModel/IdentityModel#70

We're still ending up with MissingMethodException System.Tuple when hitting the controllers. It is a aspnet core 2 web app targeting net461.

@leastprivilege

This comment has been minimized.

Copy link

commented Nov 12, 2017

@AlexGhiondea could you please work with @tstojecki and us to resolve that issue. We are relying on your technology - and I'd love to see a bit more passion on your side fixing problems like this.

@AlexGhiondea

This comment has been minimized.

Copy link
Member Author

commented Nov 13, 2017

@leastprivilege sorry for the delay in replying. @terrajobst - any ideas?

@tstojecki @leastprivilege can you please share a repro so that we can investigate?

@joperezr

This comment has been minimized.

Copy link
Member

commented Nov 13, 2017

I'm inspecting the net461 binary from your package @leastprivilege and something did catch my eye. I saw that you have a reference to System.Net.Http with a higher version that the one for the .NET 4.6.1 Targeting pack (You are referencing version 4.1.1.2 when the one on the targeting pack is 4.0.0.0) This leads me to believe that when you are building this IdentityModel.dll you have other .NET Core based dependencies which is causing your library to build against the Support package who is bringing these higher versions. If this is the case, then your consumers need to pull in that Support package or else they can end up being in torn states like @tstojecki . Do know that this specific issue with the higher versions is one that we are currently working to fix in the next release of VS, but for now, @tstojecki can you try adding to your net461 aspnet core project the following code:

<PropertyGroup>
   <_HasReferenceToSystemRuntime>true</_HasReferenceToSystemRuntime>
</PropertyGroup>

Let us know if that fixes your issue.

@leastprivilege

This comment has been minimized.

Copy link

commented Nov 14, 2017

This leads me to believe that when you are building this IdentityModel.dll you have other .NET Core based dependencies which is causing your library to build against the Support package who is bringing these higher versions.

Sorry I don't understand what that means.

Here's the repo

https://github.com/IdentityModel/IdentityModel2

Please have a look and tell me what is wrong.

Are there any docs I am missing that could help people build libraries that actually work?

@joperezr

This comment has been minimized.

Copy link
Member

commented Nov 14, 2017

Please have a look and tell me what is wrong.

Nothing is wrong with your library, the problem here is the tooling. Sorry for not making that clear 😄.

Sorry I don't understand what that means.

What I meant by that is that one of your dependencies (when building your library for 461) is either netstandard, or System.Runtime based. This causes our logic to include what we call the support package as references when building your library for 461. This support package, contains shims that will enable those netstandard/System.Runtime references to work on 461. The problem, is that those shims have higher assembly versions than the ones that we have inbox (this is a bug in our side) which causes your resulting IdentityModel.dll to depend on System.Net.Http version 4.1.1.2 instead on the one from 4.0.0.0 which comes inbox. These issues are being addressed for the next version of the VS tooling (15.5) but unfortunately on the mean time, consumers of your library would have to add a property to their project in order for things to work. That property is the one I sugested to @tstojecki above.

@leastprivilege

This comment has been minimized.

Copy link

commented Nov 14, 2017

ok thanks for the clarification.

@erikbra

This comment has been minimized.

Copy link

commented Nov 14, 2017

State of .NET Tooling for the time being... not excellent. At all.

@tstojecki

This comment has been minimized.

Copy link

commented Nov 15, 2017

Thanks for your input @joperezr and @leastprivilege
As that was a blocking issue for us we ended up upgrading and targeting 4.7 in our projects, which resolved it. I have just tried switching the projects back to 4.6.1 but I no longer get that error. Not sure, could be that I would have to uninstall .net framework 4.7 and I am not in a great place to do that.
If I get back to where this issue occurs again, I will be sure to try the config option.

@Shashanka77

This comment has been minimized.

Copy link

commented Nov 16, 2017

@joperezr and @AlexGhiondea I have two issues I would like to discuss.

  1. "What I meant by that is that one of your dependencies (when building your library for 461) is either netstandard, or System.Runtime based" -
    In the above sentence, I did not understand the phrase "either netstandard or System.Runtime based" what does this exactly mean?

  2. We have a WPF application targetting .NET Framwork 4.7.1 that consumes several .netstandard2.0 libraries. The application runs fine in Dev ENv (ie. VS 2017 debug mode). But after installing the WPF app via publish option, We are getting runtime error at application launch "Could not load file or System.Net.Http, Version 4.1.1.2 or one of its dependencies. The System.IO.FileNotFoundException could not load file or assembly System.Net.Http, Version 4.0.0.0 or one of its dependencies.

Do recommend to resolve this by compiling one of our several .netstandard lib with following?

<_HasReferenceToSystemRuntime>true</_HasReferenceToSystemRuntime>

I am not sure what assembly is actually trying to these two version of System.Net.Http and why both versions are not getting picked at runtime.

Thank you

@joperezr

This comment has been minimized.

Copy link
Member

commented Nov 16, 2017

In the above sentence, I did not understand the phrase "either netstandard or System.Runtime based" what does this exactly mean?

When we say that an assembly is netstandard based is one where the System.Object type it was built against was in netstandard.dll. A System.Runtime based, it's the same but when System.Object lives in System.Runtime.dll. Usually, if your assembly targets netstandard1.* then you are probably System.Runtime based, and if you target netstandard2.0 then you are netstandard based.

For the second issue, what version of VS are you using in order to build your app? We have a few known issues with System.Net.Http when trying to run a 4.7.1 app with a netstandard2.0 component. These issues are already fixed on the next version of VS (15.5), So I do expect that once you upgrade to 15.5 then these issues would go away.

Do recommend to resolve this by compiling one of our several .netstandard lib with following?

For the meantime unfortunately, setting the property won't help you when you are targeting 4.7.1, as it would still not fix your issue. Is there a specific reason why you need to target 4.7.1 with your WPF app? I ask this because one workaround, could be to retarget your WPF app to a lower version of the framework (4.6.1 - 4.7) and set the _HasReferenceToSystemRuntime property on the WPF project in order to get things working while we ship 15.5.

@pranavkm

This comment has been minimized.

Copy link
Contributor

commented Nov 16, 2017

@joperezr is there a build of the 2.2. preview SDK that addresses this?

@GSPP

This comment has been minimized.

Copy link

commented Oct 9, 2018

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.

dotnet/corefx#32587
dotnet/corefx#32561
#481
#567
#558
#887
#891
dotnet/corefx#32610
dotnet/corefx#30642
dotnet/corefx#32757
#895
#877
#521
#295
#476
#184
#936
#941
dotnet/corefx#33148
NuGet/Home#7440
dotnet/corefx#31532
dotnet/corefx#22781
dotnet/corefx#23306
dotnet/corefx#29622
dotnet/corefx#9846
dotnet/corefx#17522
dotnet/corefx#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.

jskeet added a commit to jskeet/nodatime that referenced this issue Jan 24, 2019

Update benchmark targets to net471 and netcoreapp3.0
net461 doesn't work when the machine has net471 installed, due to
dotnet/standard#567 (which is very
unfortunate).

jskeet added a commit to nodatime/nodatime that referenced this issue Jan 24, 2019

Update benchmark targets to net471 and netcoreapp3.0
net461 doesn't work when the machine has net471 installed, due to
dotnet/standard#567 (which is very
unfortunate).

herebebeasties added a commit to herebebeasties/DeepEqual that referenced this issue Feb 14, 2019

Add net461 target to work around ValueTuple missing method exceptions
See dotnet/standard#567 for context here.
I ran into this while using `SetComparison.Compare(...)` which is all public DeepEquals API. This manifests itself like so:
```c#
	[{System.MissingMethodException}: 'Method not found: 'System.ValueTuple`2<DeepEqual.ComparisonResult,DeepEqual.IComparisonContext> DeepEqual.SetComparison.Compare(DeepEqual.IComparisonContext, System.Object, System.Object)'.']
```

HofmeisterAn added a commit to HofmeisterAn/dotnet-testcontainers that referenced this issue Feb 27, 2019

@terrajobst

This comment has been minimized.

Copy link
Member

commented Mar 13, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.