1.The target framework of my project is net472
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
@Varorbc does it cause any problems? What are the symptoms?
Could not load file or assembly 'System.ComponentModel.Annotations, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
my test demo https://github.com/Varorbc/Test
@karelz
a library "X" targets System.ComponentModel.Annotations nuget but only has netstandard2.0
as a framework. to it has a ref to the version from System.ComponentModel.Annotations.dll from the netstandard part of the package. then a net472 application tries to use both System.ComponentModel.Annotations and "X" nugets. u now have a binding conflict.
Not to mention if you are trying to debug something in production and there are all kinds of version mistmacthes between nugets and what is in prod, it make it very difficult to rull out some kind of deployment/build pipeline issue
the v 4.5 System.ComponentModel.Annotations nuget
file versions
assembly versions
I'm seeing similar issues using System.ComponentModel.Annotations package version 4.6.0-preview.18604.2.
cc @divega @ajcvickers
@ericstj Was an assumption supporting these lines broken in the past year?
``` xml
````
.NET Framework test project redirects versions 0.0.0.0-4.2.0.0 to 4.2.0.0
That's the problem. It sounds like the .NETFramework project hasn't referenced the package and is instead picking up the .netstandard reference. If you examine the assembly version of the .NETFramework reference assembly in the package you will see it has 4.2.2.0. /cc @joperezr
You should either reference the package in the NETFramework test project, or enable PackageReference so that transitive dependencies flow to the test project.
note if u crack open some of those assemblies they are purely type forwarding. the weird thing is they are often typeforwarding to types in an assembly with a diff assembly version.
eg 4.4.1\lib\net461\System.ComponentModel.Annotations.dll
(assembly version 4.2) typeforwards to System.ComponentModel.DataAnnotations, Version=4.0.0.0
...or enable PackageReference...
We鈥檙e using PackageReference. I鈥檒l dig a bit more...
yeah in my repros of this issue i was also using PackageReference
@SimonCropp All the type forwarding and mismatched versions are normal. There鈥檚 a lot of .NET history surrounding these tangled assemblies. Luckily when it鈥檚 all working correctly, most people can ignore the ugly details. 馃槅
@bricelam yeah i figured we were dealing some long history of technical debt here :)
cc @ryanbrandenburg (Who is seeing the same issue on another codebase)
See also https://github.com/aspnet/EntityFrameworkCore/issues/13268
I have been trying for months to get answers on this. The response keeps being that it's going to be documented how to make it work. But we haven't seen any documentation yet, and both myself and customers have been tearing their hair out trying to make it work.
@ericstj any thoughts here?
Got to the bottom of our issue: We were using the the Microsoft.NETFramework.ReferenceAssemblies package at build time then our tests compiled code via Roslyn but didn't reference the assemblies in Microsoft.NETFramework.ReferenceAssemblies.
@danmosemsft the problems here as @ericstj already pointed out are due to using packages.config instead of PackageReference. All of the instances that I've investigated around this issue are caused by transitive dependencies not flowing because of the use of packages.config. In order to fix this issue, users need to either manually add a reference to System.ComponentModel.Annotations package to their application, or they need to switch their project to use PackageReference instead which would flow the transitive dependencies.
My bad, I somehow missed that comment. If there is no action for us, we can close this right?
@joperezr @danmosemsft I would like to point out that I tried changing everything to package references and so did the customer. It still failed. So at least in my experience telling people to do this is not tha answer.
isnt this repro already using packagrereferences https://github.com/dotnet/corefx/issues/33643#issuecomment-441834688 ?
@SimonCropp I just tried that project locally with the latest VS, and I see that: 1) System.ComponentModel.Annotations.dll (version 4.2.1.0) is copied to the output folder, and 2) An app.config file binding redirect is generated successfully with the following contents:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<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>
That binding redirect is causing the app to work just fine at runtime, I get the following output:
@joperezr Binding redirection is certainly possible, but fixing the assembly version is the best approach
Assembly version isn't wrong. Your NServiceBus.DataAnnotations dependency targets netstandard2.0 for which the assembly version of System.ComponentModel.Annotations is 4.2.0.0. That said, you are running on .NET Framework, for which this assembly has been patched in the package, and since it is patched, it has a new assembly version: 4.2.1.0. Because of this, NServiceBus.DataAnnotations will look for the 4.2.0 version of the assembly, but will get 4.2.1 instead. In short, this is all caused because you are using an assembly that was targeting .NET Standard, and running on .NET Framework, which is totally supported, but requires assembly redirection like this in some cases.
I would also like to point out that I and the customer also tried adding binding redirects everywhere possible and still could not make this work.
Oh I see I did get a repro with the NServiceBus test, so the Test2 project. That happens because by default we don't generate dll config files so there is no way to set the binding redirect in that case. In order to force generate the dll config with the binding redirect, just add <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
property to that project and try to build and launch it again. This time, everything should work normally.
@joperezr Yep, tried that too. Didn't work for me.
The only reason why that wouldn't work would be if the NServiceBus host doesn't honor the dll config when starting up an AppDomain. If you launch(and enable) the fuslogvw utility you should be able to see when the error happens, to see if the host looked at the dll config or not.
@joperezr I was trying to make the repro from work https://github.com/aspnet/EntityFrameworkCore/issues/13268. I don't think NServiceBus was involved. I and the customer likely did something wrong.
If there is clear guidance somewhere on what should work, I'll point people to that and let it be. However, everything that has been mentioned here so far as already been suggested before and found not to work. That either means we're doing it wrong, or the guidance is wrong.
What I'm really looking for at this point is a clear place to point people for the guidance, and a clear place they can report issues when the guidance doesn't work.
IMO no binding redirect should be needed when referencing a single version of one package.
Another similar case reported here: https://github.com/aspnet/EntityFrameworkCore/issues/14368
did just a little extension on my data model. adding the migration resulted in a wired problem with needed to configure the foreign key as nullable (see a former post on that problem) and now not being allowed to have the key nullable.
So I did a remove-migration -Context blahContext AND NOW GUESS WHAT:
System.IO.FileLoadException: Die Datei oder Assembly "System.ComponentModel.Annotations, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"...
etc..
So now I need to undo the migration by hand?
is there an solution for this issue?
@ravenboilinux if you have a minimal repro of the problem, we can take a look at it and see if one of the above solutions fix the issue in your case.
We have tried manually adding System.ComponentModel.Annotations package and switching to PackageRegerence both did not work to solve the issue
That repo is not minimal unfortunately (only the code is already about 1.3 gb), IIRC it requires specific SDKs to be present on the machine to be even able to start to build.
this is the bare repo that is needed to complete the test to throw the error.
here is the Exception that I get
Exception:
System.TypeLoadException: Could not load type 'System.ComponentModel.DataAnnotations.Schema.InversePropertyAttribute' from assembly 'System.ComponentModel.Annotations, Version=4.2.1.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.Lazy
1.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.
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredServiceT
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_Model()
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.get_EntityType()
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet
1.get_EntityQueryable()
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.System.Linq.IQueryable.get_Provider()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.Include[TEntity,TProperty](IQueryable
1 source, Expression1 navigationPropertyPath)
at MGFConfiguration.MGFConfigurationProvider.Load() in E:\Code\IS\InnerSanctum\Servers\src\Config\MGFConfiguration\MGFConfigurationProvider.cs:line 30
at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList
1 providers)
at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
at MGF_Photon.PhotonApplication.Setup() in E:\Code\IS\InnerSanctum\Servers\src\MGF.Photon\PhotonApplication.cs:line 114
at Photon.SocketServer.ApplicationBase.PhotonHostRuntimeInterfaces.IPhotonControl.OnPhotonRunning()
at PhotonHostRuntime.PhotonDomainManager.PhotonPlainAppDomainBehavior.PhotonRunning()
at PhotonHostRuntime.PhotonDomainManager.PhotonRunning()
One thing I was looking within the System.ComponentModel.Annotations.dll using dotpeek, and I only see two class FxResources.System.ComponentModel.Annotations.SR, and System.SR, two Resource files, and two assembly ref(mscorlib, and,System.ComponentModel.DataAnnotations) but nothing else.
I just tried your repro and it works fine for me:
One thing I was looking within the System.ComponentModel.Annotations.dll using dotpeek, and I only see two class FxResources.System.ComponentModel.Annotations.SR, and System.SR, two Resource files, and two assembly ref(mscorlib, and,System.ComponentModel.DataAnnotations) but nothing else.
Correct, the reason why you see that is because System.ComponentModel.Annotations.dll in .NET Framework is a facade that just type forwards to System.ComponentModel.DataAnnotations. That means that if you check with dotpeek, you should be able to see this:
Which means that when this type is trying to be loaded from this assembly, it will be instead looked for in your System.ComponentModel.DataAnnotations.dll installed on your GAC, which should have the type since .NET Framework 4.5+. My only suggestion here would be to make sure that your .NET Framework installation is correct, and that you do make sure that this type exists correctly in your GAC. One other thing you could try to diagnose this further, would be to use fuslogvw to log the bind to disk that is failing, so that we can figure out why it is not finding the type from the GAC.
Sorry after I posted that comment I saw the TypeForwardedToAttribute in the assembly properties, something that I am not use to. My .NET frameworks (from 3.5 to current version that vs allows) are all installed by the visual studio installer. The assembly that is has the type is in the GAC. How do you use fuslogvw?
Any thoughts on this
https://github.com/dotnet/corefx/issues/33643#issuecomment-452451857 ?
@SimonCropp why do you think that? Are you sure it is truth in practice?
binding redirects are to resolve version conflicts. if u only ref one version, with no diamond dependencies, there should be no conflicts and no binding redirects.
@SimonCropp while compelling idea, unfortunately the reality is more complex than that :(.
You can have collisions between references. You can have collisions with Framework built-in versions. You can have collisions with assemblies in GAC, or publisher policies. Binding redirects are mechanism to deal with all these problems (or cause more).
Addressing diamond dependencies is just one of the main scenarios.
Rather than jumping to conclusions how we think it should work, let's try to understand what is broken and why it is broken and let's deal with that.
How do you use fuslogvw?
Here is a good link that should get you started: https://docs.microsoft.com/en-us/dotnet/framework/tools/fuslogvw-exe-assembly-binding-log-viewer . Basically fuslogvw is a very useful tool whenever you get errors with TypeLoadExceptions, AssemblyLoadExceptions, FileNotFoundExceptions and MemberNotFoundExceptions. It helps by telling you exactly which assemblies each process is loading and also will tell you where did it look for a certain assembly in case it wasn't found.
@joperezr
I repaired my visual studio and the the .net frameworks and still get the error.
I tried the fuslogvw(which is a useful tool that i did not know about(
I found the problem the runtime is looking within C:\ProgramData\Red Gate.NET Reflector\DevPath for dlls, and it finds the System.ComponentModel.Annotation.dll however that version of the dll does not have the TypeForwardedToAttribute to the System.ComponentModel.DataAnnotations.dll. How do you reset or remove the DEVOVERRIDE so that it looks into the GAC
If you are seeing that, it is most likely that you have DEVPATH
environment variable defined. Here is some info about that: http://ntcoder.com/bab/2014/08/28/how-to-locate-net-assemblies-by-using-devpath/
Unsetting that variable might do the trick.
BTW, fuslogvw is a very powerful tool but it is dangerous if you don't remember to disable the logs after you are done using it. If you forget to do it, then you will eventually run into issues where your whole disk will be filled with binding logs.
I have the same problem, any solution?
It is really bad thing. almost 20 years ago, when we said Goodbye --COM dll hell and embraced brand dotnet... but right now what happened? the same thing.. maybe worse. wish MS reconsiders the way for releasing production component(dlls).
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.
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.
@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.
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.Lazy
1.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](IInfrastructure
1 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_0
1.
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.
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.
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:
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.
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 ;-)
@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>
@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.
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
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)
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.
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
.
@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.
@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.
@joperezr It's a different day and the binding redirect is now taking effect - assembly load works as expected. Thanks for the pointer.
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.
@joperezr can you please help me out here and explain what the action item here is?
@ViktorHofer What is the solution to this issue?
@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.
@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.
@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:
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:
System.ComponentModel.Annotations
is "OOB .NET Standard" libraryIn 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:
```powershell
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
@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?
@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
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.
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
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:
<PropertyGroup>
<TargetFrameworks>netstandard2.1;net472</TargetFrameworks>
</PropertyGroup>
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?
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
@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?
Most helpful comment
@joperezr @danmosemsft I would like to point out that I tried changing everything to package references and so did the customer. It still failed. So at least in my experience telling people to do this is not tha answer.