dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.98k stars 4.66k forks source link

System.ComponentModel.Annotations version is inconsistent #27975

Closed Varorbc closed 4 years ago

Varorbc commented 5 years ago

Detailed repro steps so we can see the same problem

1.The target framework of my project is net472

  1. the target framework for the package is netstandard2.0

3.the package depend on System.ComponentModel.Annotations

4.When my project restores the package(System.ComponentModel.Annotations), the net461 package is restored

5.NServiceBus.DataAnnotations restores the package(System.ComponentModel.Annotations),the netstandard2.0 package is restored

bvandehey commented 5 years ago

I'm having the same issue. In my case, it is occurring when I run the Add-Migration command for EF Core 2.2.3. The solution was to add binding redirects to the ef.exe by creating an ef.exe.config in the following folder: ~.nuget\packages\microsoft.entityframeworkcore.tools\2.2.3\tools\net461\any

My project is a .NET 4.7.2 project using the new SDK style csproj. This started occurring when I upgraded from EF6 to EF Core.

JRBonnema commented 5 years ago

bvandehey : Problem indeed mostly occurs in solutions that are both using .Net framework and .Net Core projects. See my comment in a related issue https://github.com/aspnet/EntityFrameworkCore/issues/13268 for a possible workaround.

karelz commented 5 years ago

@wtgodbe can you please look into it? It is not clear if there is any repro we can try based on last comments ... if there is none, we should ask for it, or close the issue.

bvandehey commented 5 years ago

Thanks. I have found a workaround. At least in my situation, the issue is with ef.exe. I wouldn't think I should need a binding redirect for that program to create a migration. And if one is needed, it should come in the nuget package.

This can be easily reproduced using the following steps:

git clone https://github.com/SynchroFeed/SynchroFeed.Core.git cd SynchroFeed.Core\ git checkout efcore-bug start SynchroFeed.Core.sln (to start Visual Studio 2017)

From Package Manager within Visual Studio 2017: Add-Migration Initial -project SynchroFeed.Command.Catalog

This generates the following stack trace: System.IO.FileLoadException: Could not load file or assembly 'System.ComponentModel.Annotations, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040) File name: 'System.ComponentModel.Annotations, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.CoreConventionSetBuilder.CreateConventionSet() at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateConventionSet(IConventionSetBuilder conventionSetBuilder) at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator) at System.Lazy1.CreateValue() at System.Lazy1.LazyInitValue() at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel() at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model() at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies() at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() at Microsoft.EntityFrameworkCore.Internal.InternalAccessorExtensions.GetService[TService](IInfrastructure1 accessor) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func1 factory) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType) at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_01.b__0() at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)`

I'm using Windows 10, Visual Studio 2017 v15.9.10, .NET Framework 4.7.2, Microsoft.EntityFrameworkCore.SqlServer 2.2.3 and Microsoft.EntityFrameworkCore.Tools v2.2.3.

st1pps commented 5 years ago

I have the same problem with EF Core 2.2.3, EF 6 6.2.0 in a .NET 4.6.1 WPF application. Part of the code comes from a custom .NET Standard 2.0 dll. I'll try to put together a 'working' minimal example asap.

Poutche commented 5 years ago

Same problem here. EF Core 2.2.4 on .NET Framework 4.61 in a winforms app. Occurs in Mycontext.MyDbSet.Load() (SqlExpress).

My first steps with Entity Framework... grrr... ;)

The Microsoft.EntityFrameworkCore.dll (version 2.2.4.0) has a reference to System.ComponentModel.Annotations, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a (unresolved)... App.Config: <?xml version="1.0" encoding="utf-8"?>

Poutche commented 5 years ago

Problem solved by using the code found here: https://stackoverflow.com/questions/50342416/azure-function-ef-core-cant-load-componentmodel-annotations-4-2-0-0 Many thanks to the author for sharing this.

obelixA commented 5 years ago

I also "solved" the problem using this code. But it is more a avoidance than a solution. Assembly loading is damn slow now. Am I the only one who finds it somehow ridiculous that this issue is unresolved over months and months while development of the assemblies continues? This must be a really, really deeply hidden problem where no developer dares to dig that a development machinery like MS cannot solve it and needs stackoverflow to offer a solution ;-)

junkbondtrader commented 5 years ago

@joperezr fuslogvw gives me the following:

*** Assembly Binder Log Entry  (5/6/2019 @ 3:46:21 PM) ***

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable  C:\Source\Application\Debug\Application.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: DisplayName = System.ComponentModel.Annotations, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 (Fully-specified)
LOG: Appbase = file:///C:/Source/Application/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = Application.exe
Calling assembly : Microsoft.EntityFrameworkCore, Version=2.2.4.0, Culture=neutral, PublicKeyToken=adb9793829ddae60.
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: No application configuration file found.
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: System.ComponentModel.Annotations, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Source/Application/Debug/System.ComponentModel.Annotations.DLL.
LOG: Attempting download of new URL file:///C:/Source/Application/Debug/System.ComponentModel.Annotations/System.ComponentModel.Annotations.DLL.
LOG: Attempting download of new URL file:///C:/Source/Application/Debug/System.ComponentModel.Annotations.EXE.
LOG: Attempting download of new URL file:///C:/Source/Application/Debug/System.ComponentModel.Annotations/System.ComponentModel.Annotations.EXE.
LOG: Attempting download of new URL file:///C:/Source/Application/ComExtensions/ComExtensions/bin/Debug/System.ComponentModel.Annotations.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\Source\Application\ComExtensions\ComExtensions\bin\Debug\System.ComponentModel.Annotations.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: System.ComponentModel.Annotations, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
WRN: Comparing the assembly name resulted in the mismatch: Build Number
ERR: The assembly reference did not match the assembly definition found.
ERR: Run-from-source setup phase failed with hr = 0x80131040.
LOG: Attempting download of new URL file:///C:/Source/Application/ComExtensions/ComExtensions/bin/Debug/System.ComponentModel.Annotations/System.ComponentModel.Annotations.DLL.
LOG: Attempting download of new URL file:///C:/Source/Application/ComExtensions/ComExtensions/bin/Debug/System.ComponentModel.Annotations.EXE.
LOG: Attempting download of new URL file:///C:/Source/Application/ComExtensions/ComExtensions/bin/Debug/System.ComponentModel.Annotations/System.ComponentModel.Annotations.EXE.
LOG: All probing URLs attempted and failed.

My .Net Framework 4.7.2 project (ComExtensions) uses PackageReference to consume a .Net Standard 2.0 project that has an indirect dependency on System.ComponentModel.Annotations 4.5.0 (Microsoft.EntityFrameworkCore.SqlServer 2.2.4 -> System.ComponentModel.Annotations 4.5.0).

The .Net Framework project has automatic binding redirection enabled and the .dll.config looks like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.ComponentModel.Annotations" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.1.0" newVersion="4.2.1.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>
joperezr commented 5 years ago

@junkbondtrader from what I can see, that binding redirect is not getting honored. Take a look at this line in particular:

LOG: No application configuration file found.

That basically means that the .dll.config was not loaded. If it was, then this would have worked as it clearly found your app-local 4.2.1.0 version of the assembly, but didn't unify to it because it didn't find a redirect. @AaronRobinsonMSFT is this expected on ComExtensions projects? @junkbondtrader how is this particular component getting loaded? That might give us more info on why the binding redirect is not getting honored.

yyjdelete commented 5 years ago

Have an similar issues for use any(No build-time warns, so it's hard to see whether it's affacted or not) library which target only ns2.0 and depend an multi-target lib with different dependencies for different target, and then use it in net472 program. And see no warns at build time, but an FileNotFoundException at runtime, seems transitive dependencies never works in that case, and no warns is shown as it does without transitive dependencies. See dotnet/sdk/issues/3103

Dapper<-System.Data.SqlClient

Struct

Main(net472)
|-Lib1(netstandard2.0)//And use `System.Data.SqlClient.SqlConnection` transitive from Lib2 directly in the lib, or use any public API which export `System.Data.SqlClient`
    |-Lib2 or [Dapper](https://www.nuget.org/packages/Dapper)
        |-System.Data.SqlClient, Version=4.5.0.0(netstandard2.0)
        |-System.Data(net451, frameworkAssembly)

Wanted:

Main(net472)
|-Lib1(netstandard2.0)//And use `System.Data.SqlClient.SqlConnection` transitive from Lib2 directly in the lib, or use any public API which export `System.Data.SqlClient`
    |-Lib2(both ns2.0 and net451 is OK) or [Dapper](https://www.nuget.org/packages/Dapper)
    |-System.Data.SqlClient, Version=4.5.0.0(net451/net461)//this one is needed as it's an runtime package, the ns2.0 version always throw `PlatformNotSupportedException`

And see no build-time error, but System.Data.SqlClient.dll is lost for the main program and an runtime expection FileNotFoundException with System.Data.SqlClient, Version=4.5.0.0, lib1 can also be publish as an nuget package without warns but the same result at runtime.

Addin Issue:

Visual Studio also show an different dependencies tree struct(Dapper ns2.0+System.Data.Client instead of net451) for the reference as the sdk does for project.assets.json.

AaronRobinsonMSFT commented 5 years ago

@joperezr I think the "ComExtensions" project mentioned above is one of @junkbondtrader's projects and not something we provide. If it is I am happy to look, but I have never heard of it.

junkbondtrader commented 5 years ago

@joperezr My .Net Framework dll is invoked via COM by an unmanaged C++ app.

Interestingly, the binding redirect isn't taking effect even after duplicating it in both the .exe.config and the machine.config.

The issue reproduces for me when the project referencing EF Core is .Net Framework (as opposed to .Net Standard, as before).

Hi @AaronRobinsonMSFT! Hope you're well :) You're correct - ComExtensions is my project name. COM interop is in the picture but I doubt that everyone experiencing this issue is using it.

junkbondtrader commented 5 years ago

@joperezr It's a different day and the binding redirect is now taking effect - assembly load works as expected. Thanks for the pointer.

tobbyioa commented 5 years ago

I had this problem for some time and tried all sorts to no avail. However, I discovered the version showing for Version 4.5.0 in the library reference properties is 4.2.1.0. When I changed the version to 4.4.1 via NuGet, the version in the properties changed to 4.2.0.0. This fixed it for me and was able to load the Swagger UI. I hope you will find this helpful.

ViktorHofer commented 5 years ago

@joperezr can you please help me out here and explain what the action item here is?

Varorbc commented 5 years ago

@ViktorHofer What is the solution to this issue?

joperezr commented 5 years ago

@Varorbc This issue had the problem that many people were having the same type of symptoms for very different root causes, so it became hard to manage, as some solutions posted worked for some folks but not for others. Instead, what we opted with is to close this issue and have people hitting similar symptoms to log new individual issues with repro steps so we can investigate isolated cases and fix each one (if needed) so we are not mixing together many different root causes.

JRBonnema commented 5 years ago

@joperezr : Did you notice that earlier six other issues were closed with a reference to this issue. So why wait for new future issues ? One can also reopen these six issues. Maybe you don't realize it, but the underlying problems causing this issue make it relatively difficult and time consuming to have solutions that include both .Net Framework and .Net Core projects, even de facto impossible in many cases. So solving the underlying problems causing this issue should in my opinion be a high priority for your company. That seems however to be difficult because in all likelihood many teams within your company will probably be involved. That is probably also the reason the problem is already there for over two years and will most likely still be there after migrating to .Net Core 3.0.

jzabroski commented 4 years ago

@Varorbc This issue had the problem that many people were having the same type of symptoms for very different root causes, so it became hard to manage, as some solutions posted worked for some folks but not for others. Instead, what we opted with is to close this issue and have people hitting similar symptoms to log new individual issues with repro steps so we can investigate isolated cases and fix each one (if needed) so we are not mixing together many different root causes.

This is the second search result in Google for "System.ComponentModel.Annotations".

@ViktorHofer @joperezr This explanation doesn't make any sense to me. Please link to the many different root causes, as this issue has cost me over 40+ hours of development time over the last 3 years since I adopted .NET Core full-time. And I am just ONE developer.

It would be very helpful if you explained to us what information you need to collect to fix this problem.

The CORE problem seems to be that the underlying DLL has to target every platform known to the .NET Ecosystem, as the following screenshot of nuget.org System.ComponentModel.Annotations demonstrates:

image

I say this is the CORE problem because I suspect the "magic" the dotnet SDK team has done with MSBuild to generate a .deps.json file doesn't work when there are this many target frameworks and the DLL has to be re-deployed any time any of these target frameworks change.

In my case, I used the following PowerShell script to determine which version of System.ComponentModel.Annotations I was building against: https://github.com/jzabroski/PowerShell-1/blob/master/GetFileProperties.ps1

I then got the ProductVersion attribute from the file, which was: 4.6.26515.06 @BuiltBy dlab-DDVSOWINAGE059 @Branch release/2.1 @SrcCode https://github.com/dotnet/corefx/tree/30ab651fcb4354552bd4891619a0bdd81e0ebdbf

Tracking backward from this commit, I see there was a type-forward added by @ViktorHofer here: https://github.com/dotnet/corefx/commit/e3f74deb999571d3f34a6b2b8011caebcf06dbfc#diff-df03b8a58b886901569279ef9bdb1d90R13 on on Oct 27, 2017. Traveling back to nuget.org (because I cannot easily infer which nuget packages shipped this commit), I can see it was shipped no earlier than 12/12/2017 via System.ComponentModel.Annotations 4.4.1. Curiously, this version of the nupkg mentions git commit hash 0f6d0a02c9cc2e766dd543ff24135f16e9a971e4. So, I went back to the corefx/tree and went to https://github.com/dotnet/corefx/tree/0f6d0a02c9cc2e766dd543ff24135f16e9a971e4 and then the commit https://github.com/dotnet/corefx/commit/0f6d0a02c9cc2e766dd543ff24135f16e9a971e4, where I can see that pkg/Microsoft.Private.PackageBaseline/packageIndex.json was updated to include 4.4.1. At this point, I'm not sure what packageIndex.json does, but I found Microsoft.Private.PackageBaseline which says:

Package used by CoreFx build infrastructure to represent the latest package versions in a release. When using NuGet 3.x this package requires at least version 3.4.

Looking at the version history for this package, it stopped being maintained on nuget.org as of 5/9/2017. Hypothesis: This package should never have been on nuget.org, because its designed for the sole consumption of the CoreFX build infrastructure. This may be causing some problems with versions of System.ComponentModel.Annotations or other dll's prior to 5/9/2017, if the build infrastructure depended on its dependencies also being published to nuget.org. - Just a guess.)

Jumping back, trawling through the commit history from the 4.4.1 release commmit hash, I can see that Viktor's typeforward fixes made it into this version: https://github.com/dotnet/corefx/commits/0f6d0a02c9cc2e766dd543ff24135f16e9a971e4/src/System.ComponentModel.Annotations

Given that Viktor implemented TypeForwardedFrom - I wonder if I can somehow implement TypeForwardedToAttribute on top of his TypeForwardedFrom. It seems like an awful idea, and I doubt there is much regression testing in the compilerservices stack on such scenarios, but hey, damned if you do, damned if you don't.

Separately, digging through the THOUSANDS of linked issues, I found this simple explanation by @joperezr 👍. I've altered his quote slightly so that it's clearer:

[System.ComponentModel.Annotations] won't work because this specific library is not inbox, its Oob [(out-of-box)].

I also found this quote by Immo, on 10//2017 in an issue tagged [dotnet-fx-compat]():

I had heard that all these System.* dlls were going to go away in netstandard 2.0 but that doesn't seem to be the case

Yes and no. If you compile against .NET Standard 2.0, your code will only be compiled against netstandard.dll. However, for backwards compatibility with .NET Standard 1.x the other DLLs are still needed.

In general, .NET Standard dependencies were never meant to be deployed by the application. The idea is that they are built into the .NET implementation you're running on. Since we had a business goal to make .NET Framework 4.6.1 work with .NET Standard 2.0, we had to provide these additional files as part of the application. This will stop being the case starting with .NET Framework 4.7.1. In all other .NET implementations (.NET Core, Mono, Xamarin, UWP) they are already built-in.

Putting these two comments together, there are TWO types of .NET Standard dependencies:

"InBox .NET Standard" "OOB (Out-of-box) .NET Standard"

For .NET Framework applications, you will always run into these System.ComponentModel.Annotations inconsistency issues, because:

  1. System.ComponentModel.Annotations is "OOB .NET Standard" library
  2. Applications have to provide these DLLs for .NET Framework 4.6.1 to .NET Framework 4.7.0, because they're always "OOB".
  3. As of .NET Framework 4.7.1, .NET Standard 2.0 assemblies should be "inbox".
  4. However, System.ComponentModel.Annotations is still not "inbox", as per @joperezr comment - no idea why that's the case.
  5. You can confirm System.ComponentModel.Annnotations is still not "inbox", by going to C:\Program Files\dotnet\packs\NETStandard.Library.Ref\2.1.0\ref\netstandard2.1 and seeing that it's not there.
  6. In fact, as the following PowerShell script shows, it's not in any dotnet.exe pack prior to .NETCoreApp3.0:

    get-childitem 'C:\Program Files\dotnet\packs\' -recurse | where name -eq "System.ComponentModel.Annotations.dll"
    
    Directory: C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.0.0\ref\netcoreapp3.0
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----        9/13/2019   2:25 AM          27000 System.ComponentModel.Annotations.dll
    
    Directory: C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----       11/15/2019   8:33 AM          27208 System.ComponentModel.Annotations.dll

    and then cross-referencing that list with the list of runtimes you have installed:

    dotnet.exe --list-runtimes
    Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
    Microsoft.AspNetCore.All 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
    Microsoft.AspNetCore.All 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
    Microsoft.AspNetCore.All 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
    Microsoft.AspNetCore.All 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
    Microsoft.AspNetCore.All 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
    Microsoft.AspNetCore.All 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
    Microsoft.AspNetCore.All 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
    Microsoft.AspNetCore.All 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
    Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.NETCore.App 1.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 1.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 1.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 1.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.WindowsDesktop.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
    Microsoft.WindowsDesktop.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Further, now let's suppose this assembly WAS added in .NET Framework 4.7.1 and you don't need to include it. Now any Nuget package published AFTER .NET Framework 4.7.1 SHOULD exclude this package as a PackageReference, otherwise you're screwed. This appears to be the current problem with FluentMigrator, and there is no build warning telling us about this problem: https://github.com/fluentmigrator/fluentmigrator/blob/9d80faaae71de0d326b2f226083be3d8d7a5c9d2/src/FluentMigrator.Abstractions/FluentMigrator.Abstractions.csproj#L45

Further, as a dirty hack, you can use PowerShell 5.0 to quickly check the actual Assembly Version attribute on the dll in your deployment folder:

[System.Reflection.Assembly]::LoadFrom("D:\source\path\to\bin\Debug\net48\System.ComponentModel.Annotations.dll")
GAC    Version        Location
---    -------        --------
False  v4.0.30319     D:\source\path\to\bin\Debug\net48\System.ComponentModel.Annotations.dll
Bert-Proesmans commented 4 years ago

@jzabroski very clear explanation, thank you. I deduce from your future note that the duration until this gets fixed encompasses both framework updates and following ecosystem updates. So we'll have to wait at least months if not years? In the meantime this is unsolvable when combining net framework and net standard libraries, because each targetted framework uses a different annotations assembly which cannot be robustly redirected?

jzabroski commented 4 years ago

@Bert-Proesmans For now, the thing to watch out for is linking a netstandard2.0 assembly from a Common package as a transitive dependency. If you then have a net48 entrypoint and the netstandard2.0 Common assembly exposes the nuget package ANYWHERE in its public API, you have a diamond dependency issue.

Obviously, can also happen with net461 and net472 but practically speaking, only net472 and net48 support netstandard2.0.

In the meantime this is unsolvable when combining net framework and net standard libraries, because each targetted framework uses a different annotations assembly which cannot be robustly redirected?

System.ComponentModel.Annotations uses attributes, which are public - there is no such thing as a private attribute. That's why System.ComponentModel.Annotations is the most common offender. In other scenarios, you might get lucky and sidestep the problem because the C# compiler and MSBuild generate magic configurations that sidestep the problem.

In terms of fixing this problem? Well, I didn't think that far, but I guess the simplest solution is for Microsoft to not close this issue and... actually fix the issue. Additionally, adopting a policy of not creating separate BuildNumbers across Frameworks is probably a good check for nuget.org - at least have a warning that this will waste developers a lot of time. But I'm not a computer scientist so maybe my idea of fixing this is not smart enough

Bert-Proesmans commented 4 years ago

Thank you for the clarification.

Indeed, assembly redirects solve some cases but only for executables. The remaining issue for me personally is test projects: Library projects do not automatically receive nor seem to respect manually defined assembly redirects. At the moment my tests fail at runtime, while the deployed project works fine. I converted one of my test projects into an executable one to keep moving forward. Sadly, I lost interaction through the Test Explorer in the process. Is there a way to make executable test projects work with test explorer? I quickly browsed some search results but haven't really seen a solution, but will keep looking.

jzabroski commented 4 years ago

You'll need a DirtyAssemblyResolveHelper in your test project and an assembly ModuleInit to create manual binding redirects. You can use Fody for that - a bit convoluted but as part of your build process, run Fody through all *.Tests.dll files https://github.com/Fody/ModuleInit

derickanderson commented 4 years ago

I was able to dodge this with .NET 4.8 test projects and .NET Standard libraries by using multi-targeting of .NET Standard 2.1 and .NET 4.7.2 in my library projects (rather than .NET Standard 2.0 individually). In the dependencies of the test project in which Annotations was used, I set up my target frameworks to look like this:

`

netstandard2.1;net472

`

daiplusplus commented 4 years ago

I was having the same issue with a PackageReference-style project targeting .NET Standard 2.0 that was being referenced by a Unit Test project (old-style csproj) that targeted .NET Framework 4.7.2.

In my case, my PackageReference was for System.ComponentModel.Annotations version 4.7.0. My solution would build fine, but whenever the DataAnnotations attributes were loaded/used on-demand then I'd get this exception:

System.IO.FileLoadException: Could not load file or assembly 'System.ComponentModel.Annotations, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

I downgraded my NuGet package reference to System.ComponentModel.Annotations version 4.4.0 and the solution builds and runs fine.

What happened between version 4.4.0 and 4.7.0 that caused System.ComponentModel.Annotations to break in .NET Framework 4.7.2 Unit Test projects?

MatthewSteeples commented 3 years ago

This problem looks to have been mis-diagnosed as a framework problem initially. I believe that the main problem is that there is a version mismatch between netstandard2.0 in the lib and ref folders. The ref folder has a version of 4.2.1.0, but the lib folder has 4.2.0.0. Version 4.4.0 of this package had both folders referenceing version 4.2.0.0, but since 4.5.0 onwards (including all of the 5.0 releases) there is a version mismatch.

This is what's causing packages.config based projects to require a binding redirect to fix the problem

viralmodi commented 3 years ago

@karelz @ViktorHofer We are seeing this issue too and the root cause is exactly what @MatthewSteeples mentioned above. Can we fix the version mismatch in "ref" and "lib" directories for .NET Standard 2.0. We have a product using this dll and targeting .NET Standard 2.0. It will be great if we can get a fixed version. Can you reopen the issue and fix it?