dotnet / standard

This repo is building the .NET Standard
3.06k stars 428 forks source link

.NET Standard issues on .NET Framework 4.7.1 #567

Closed AlexGhiondea closed 5 years ago

AlexGhiondea commented 7 years ago

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: https://github.com/Microsoft/dotnet-framework-early-access/issues/9

The following types are potentially impacted by this issue.

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:

Petermarcu commented 6 years ago

@Andrew-MSFT as FYI

joperezr commented 6 years ago

@gulbanana @EvanHaklar A workaround was posted on the original ClickOnce issue https://github.com/dotnet/standard/issues/529#issuecomment-366695368 by @onovotny (Thanks!). Can you guys try if that will solve your issues temporarily while Click Once team gets the propper fix in?

GSPP commented 6 years ago

Can you provide the list of assemblies affected? I understand that projects targeting .NET 4.7.1 must now manually delete binding redirects for all assemblies that were added to .NET 4.7.1. I came to this issue because of System.Security.Cryptography.Algorithms breaking. Are there more?

joperezr commented 6 years ago

@GSPP you shouldn't delete any binding redirects that get added to your app by our tooling, even when targetting 4.7.1. If you update your VS to latest and build your project, and if your project depends on an assembly (directly or indirectly) that is .NET Standard-based, I would expect 12 extra assemblies to get copied to your output directory and also some binding redirects added for them. The list of the 12 is:

System.Data.Common.dll
System.Diagnostics.StackTrace.dll
System.Diagnostics.Tracing.dll
System.Globalization.Extensions.dll
System.IO.Compression.dll
System.Net.Http.dll
System.Net.Sockets.dll
System.Runtime.Serialization.Primitives.dll
System.Security.Cryptography.Algorithms.dll
System.Security.SecureString.dll
System.Threading.Overlapped.dll
System.Xml.XPath.XDocument.dll

Without them, or without the binding redirects, it is very likely that your app will run into runtime issues like: MissingMethodExceptions, MissingTypeExceptions, or FileNotFoundExceptions

GSPP commented 6 years ago

There exists the following issue with System.Runtime.dll:

My web app on .NET 4.7.1 references the latest NuGet package. This package configures a reference to 4.1.1.0. It adds a binding redirect to 4.1.2.0. When I inspect the DLL in Reflector it does not reference System.Runtime at all.

The web app also uses an old version of Microsoft Unity which contains a reference to System.Runtime 4.0.0.0. My web app compiles OK but when I run it I get:

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.
=== Pre-bind state information ===
LOG: DisplayName = System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 (Fully-specified)
LOG: Appbase = ...
LOG: Initial PrivatePath = ...
Calling assembly : Microsoft.Practices.Unity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=6d32ff45e0ccc69f.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: ...\web.config
LOG: Using host configuration file: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet.config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Redirect found in application configuration file: 4.0.0.0 redirected to 4.1.2.0.
LOG: Post-policy reference: System.Runtime, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

So Unity now wants to use System.Runtime. Unfortunately, it was not copied to the bin directory.

I'm unsure about how to fix this. Deleting the binding redirect in web.config works but I'm hesitant to modify what the NuGet package automatically did.

This seems to be a tooling bug. Should this not just work?

@joperezr

joperezr commented 6 years ago

@GSPP this seems to be a different case than the rest of the ones on this issue. Do you mind opening a new one with either a simple repro (preferred!) or a msbuild binlog (run msbuild yourProject.csproj /t:rebuild /bl from a developer prompt) so that we can take a look?

GSPP commented 6 years ago

@joperezr I have created a new issue with a repro solution.

GSPP commented 6 years ago

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.

terrajobst commented 5 years ago

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