-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
System.ComponentModel.Annotations version is inconsistent #27975
Comments
@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 |
a library "X" targets System.ComponentModel.Annotations nuget but only has 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 |
I'm seeing similar issues using System.ComponentModel.Annotations package version 4.6.0-preview.18604.2.
|
@ericstj Was an assumption supporting these lines broken in the past year? <!-- Must match version supported by frameworks which support 4.2.* inbox.
Can be removed when API is added and this assembly is versioned to 4.3.* -->
<AssemblyVersion Condition="'$(TargetsNetFx)' != 'true'">4.2.0.0</AssemblyVersion>
<IsPartialFacadeAssembly Condition="'$(TargetsNetFx)' == 'true'">true</IsPartialFacadeAssembly> |
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 |
We’re using PackageReference. I’ll dig a bit more... |
yeah in my repros of this issue i was also using |
@SimonCropp All the type forwarding and mismatched versions are normal. There’s a lot of .NET history surrounding these tangled assemblies. Luckily when it’s 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 dotnet/efcore#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. |
See also dotnet/efcore#13956 |
@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 |
@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. |
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:
From Package Manager within Visual Studio 2017: This generates the following stack trace: 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. |
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)... |
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 |
I also "solved" the problem using this code. But it is more a avoidance than a solution. Assembly loading is damn slow now. |
@joperezr fuslogvw gives me the following:
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:
|
@junkbondtrader from what I can see, that binding redirect is not getting honored. Take a look at this line in particular:
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. |
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. Dapper<-System.Data.SqlClient Struct
Wanted:
And see no build-time error, but 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 |
@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. |
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: dotnet/corefx@e3f74de#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 dotnet/corefx@0f6d0a0, 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:
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:
I also found this quote by Immo, on 10//2017 in an issue tagged dotnet-fx-compat:
Putting these two comments together, there are TWO types of .NET Standard dependencies: "InBox .NET Standard" For .NET Framework applications, you will always run into these System.ComponentModel.Annotations inconsistency issues, because:
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")
|
@jzabroski very clear explanation, thank you. |
@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.
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. |
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:
|
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
I downgraded my NuGet package reference to What happened between version 4.4.0 and 4.7.0 that caused |
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 This is what's causing packages.config based projects to require a binding redirect to fix the problem |
@karelz @ViktorHofer |
Detailed repro steps so we can see the same problem
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 restored5.NServiceBus.DataAnnotations restores the package(
System.ComponentModel.Annotations
),the netstandard2.0 package is restoredThe text was updated successfully, but these errors were encountered: