Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Xero.NetStandard.OAuth2 seems to be referencing the wrong version of System.ComponentModel.Annotations #224

Closed
JohnAtMiTek opened this issue Sep 15, 2020 · 22 comments
Assignees
Labels
OAuth 2.0 Issues related to the OAuth 2.0 library Status: In Discussion

Comments

@JohnAtMiTek
Copy link

JohnAtMiTek commented Sep 15, 2020

SDK you're using (please complete the following information):
Xero.NetStandard.OAuth2 v3.4.1
Xero.NetStandard.OAuth2Client v1.2.1

Describe the bug
I am migrating our Windows C# desktop app’s Xero component from OAuth1 to OAuth2 and I am having problems with a FileLoadException for System.ComponentModel.Annotations.dll when attempting to get the list of Accounts from Xero.
I have created a test program that approximately matches the flow through our main program’s Xero communications, and ensured that I am using all of the exact versions of nuget packages specified as dependencies for both the Xero OAuth2 SDK and the Xero Client SDK.

To ensure that I got the right versions of the dependencies, I did not rely on the nuget functionality inside Visual Studio.
I manually downloaded each of these nuget packages, unzipped them, navigated to each of their ‘lib\netstandard2.0’ directories and copied the .dll into my XeroTestApp’s executable directory.

The details of the exception are:
System.IO.FileLoadException
HResult=0x80131040
Message=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)
Source=XeroAPI
StackTrace:
at XeroAPIWrapper.XeroAPI.GetAllActiveAccountsAsync()
at XeroTest.MainWindow.<Button_Click>d__1.MoveNext() in C:\Users\xxxxx\Documents\Visual Studio 2019\Projects\XeroTest\XeroTestApp\MainWindow.xaml.cs:line 36

The FusionLog text from the exception is:
Pre-bind state information
LOG: DisplayName = System.ComponentModel.Annotations, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
(Fully-specified)
LOG: Appbase = file:///C:/Users/xxxxx/Documents/Visual Studio 2019/Projects/XeroTest/XeroTestApp/bin/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : Xero.NetStandard.OAuth2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null.

LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Users\xxxxx\Documents\Visual Studio 2019\Projects\XeroTest\XeroTestApp\bin\Debug\XeroTestApp.exe.Config
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: Attempting download of new URL file:///C:/Users/xxxxx/Documents/Visual Studio 2019/Projects/XeroTest/XeroTestApp/bin/Debug/System.ComponentModel.Annotations.DLL.
WRN: Comparing the assembly name resulted in the mismatch: Build Number
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.

If you view the Windows Properties for this dll, you can see that the file version and product version are 4.6.26515.6. Unfortunately, the Properties window doesn't show the Assembly version, but if you open this dll in Visual Studio (open the file using the 'resource editor' option), you can see that the Assembly Version is 4.2.1.0.

Why is the Xero dll looking for System.ComponentModel.Annotations v4.2.0.0, when the dll in the nuget package specified as a dependency is v4.2.1.0 ?

Another thing I noticed in the error details is that Xero.NetStandard.OAuth2.dll has Version=0.0.0.0 !! You should probably fix that :-)

Thanks.

@JohnAtMiTek
Copy link
Author

Hello again.

I think I might have found the cause of the problem.

I decided to build the Xero SDK dlls myself to see if I could find a solution to this problem. While looking through all the files generated by the build process for mentions of system.componentmodel.annotations, I discovered a file called project.assets.json in Xero.NetStandard.OAuth2\obj. In this file, is a "targets" section, and in that is a section for "system.componentmodel.annotations\4.5.0":

  "System.ComponentModel.Annotations/4.5.0": {
    "type": "package",
    "compile": {
      "ref/netstandard2.0/System.ComponentModel.Annotations.dll": {}
    },
    "runtime": {
      "lib/netstandard2.0/System.ComponentModel.Annotations.dll": {}
    }
  }

Notice there are "compile" and "runtime" sections, and they point to different folders "ref" and "lib".
I checked the two dlls in those folders, and they have DIFFERENT assembly versions ! The one in the ref folder (used for compiling) is 4.2.0.0 and the one in the lib folder (used when executing) is 4.2.1.0.

That explains why the dll included in the runtime folder is 4.2.1.0 but the Xero dll is looking for 4.2.0.0.

I know virtually nothing about nuget (this OAuth migration project is my first exposure to it), so I don't understand the implications of these differences, or how to fix them. What I do know is that it's not my responsibility :-)

Thanks.

@jenksguo jenksguo self-assigned this Sep 18, 2020
@jenksguo
Copy link
Contributor

Hi @JohnAtMiTek, sorry, I have not completely understood the issue.

It seems the dll created during compilation created two versions for compile & runtime? There is no control we can put in to suggest how dlls are generated. I think it relies on the framework itself to interpret is it right?

We are targeting Netstandard 2.0 so, when it was build in netcore 3.1 there was no such a dll conflict.

@jenksguo jenksguo added OAuth 2.0 Issues related to the OAuth 2.0 library Status: In Discussion labels Sep 18, 2020
@JohnAtMiTek
Copy link
Author

Hi @jenksguo,

If you look at the System.ComponentModel.Annotations files installed by nuget (c:\users<user>.nuget\packages\system.componentmodel.annotations\4.5.0, you'll see two folders - lib and ref. In each of those is a netstandard2.0 folder, and in each of those is a dll. Open the dlls in Visual Studio using the Open File command, then look at the version info. The Assembly Version for the dll in the lib folder is 4.2.1.0 while the Assembly Version for the dll in the ref folder is 4.2.0.0.

Now, a random inspection of a bunch of other nuget packages installed on my computer only contain a lib folder (not a ref folder), so I assume the nuget system is designed to use the dlls in the lib folder when it's copying dlls to the output folder when building, and that's what appears to be happening. The problem is that Xero seems to be looking for v4.2.0.0 at runtime.

I'm kind of surprised that nobody else seems to be having this problem (or maybe they are having it but are working around it and not reporting it)...

Thanks.

@kanebullen
Copy link

Hi. I'm getting exactly the same issue here - am in the process of trying to move over from oauth1 to oauth2 for an integration.

Have spent the last few hours in DLL hell, thinking that it must be something I've done wrong. But seeing above, I'm thinking that perhaps it's not a problem at this end.

@MatthewSteeples
Copy link
Contributor

Looks to be a framework problem. You can fix it with the following binding redirect temporarily

<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>

@kanebullen
Copy link

I had already done that, but unfortunately didn't help at all.

Weirdly, if I create a brand new project and solution targeting the same framework, I don't get the same issue (I was doing that to provide sample code to reproduce the issue). So it must be something to do with other dependencies in our project.

The issue is not with the Oath2 authorisation code - that works fine - it's just the main API where dealing with data.

Have resorted to building my own wrapper and calling the API directly.

@JohnAtMiTek
Copy link
Author

Thanks for that link, @MatthewSteeples. After further investigation, I also think this is probably most likely a problem with System.ComponentModel.Annotations, rather than the Xero dlls themselves. After reading a lot of the posts on that issue you linked to, and with my other experiences with Microsoft, I'm not going to hold my breath waiting for them to fix it.

Fortunately, I was able to work around the problem using a binding redirect, as you suggest. It's a messy workaround, though, because I've had to force that change on all of our users worldwide, rather than just those 5 or 10 who are using our Xero plugin because binding redirects can't be applied at the dll level, only the application level. Hopefully it doesn't screw anything else up !

@jenksguo
Copy link
Contributor

Hi @JohnAtMiTek @kanebullen, I will leave this issue open for discussions. Let me know if there is anything I should address on the OAuth2Client and the main SDK it self. :-)

@jenksguo
Copy link
Contributor

Hi @JohnAtMiTek @kanebullen, I am closing this issues for now. Please re-open if there are any more issues to discuss.

@nmarkroberts
Copy link

nmarkroberts commented Feb 9, 2021

This issue is causing me a problem right now, I have invested about 20 hours so far, and I wonder if anyone has any further insight?

@kanebullen solved the problem by writing his own wrapper.

@JohnAtMiTek was able to make the problem go away using a binding redirect (as described by @MatthewSteeples) but that's not working for me.

I can run my code successfully on my development machine, but as soon as I attempt to deploy to live I hit this snag.

It seems the problem does not lie with Xero.NetStandard.OAuth2 itself but the remedy may be to change its expected version of Annotations.

I can provide more detail as required, but for now this comment is fishing for someone who already solved the problem.

@jenksguo Could you please re-open this issue because it hasn't gone away, thanks
image

@kanebullen
Copy link

@nmarkroberts Yep, I ended up having to write my own wrapper - which was less than ideal (and 30hrs+ work that we can't charge any client for). But at least it works now.

@wobinb wobinb reopened this Feb 10, 2021
@blueyugo
Copy link

Had the same issue as @kanebullen where new project did not throw the error, but our existing private app which we are upgrading threw it.

After looking further in the existing binding redirects we found a duplicate key for System.Data.SQLite. After removing it the issue was solved.
This duplicate key has come from the original Oauth1 XeroAPI SDK, but didn't cause any issues until now.

image

@nmarkroberts
Copy link

nmarkroberts commented Feb 12, 2021

Update:

I am now able to deploy my code successfully to a different server after applying the bindingRedirect workaround.
I have also worked out that the ultimate problem is NuGet installing the "wrong" version of the DLL during our Build process.

We have three factors contributing to this issue:

(1) The strange ambiguity of the DLL versioning as described above and elsewhere
(2) The requirement for a bindingRedirect in the web.config of the target server - which will always be a different file from the one on the development machine
(3) The Nuget update run which is part of our Build Server process.

We use TeamCity on our Build Server for the routine build. It has 21 build steps including "Update NuGet Packages." It looks like NuGet is installing an unexpected version of the DLL, although on inspection it claims to be 4.2.1.0
image

Once again this is not a problem in the Xero package per se but it's a problem some of us have to overcome to be able to use it.

@rakkers
Copy link

rakkers commented Feb 13, 2021

I'm also having this problem. I've tried the re-direct but that's not working for me. Does anyone have any other suggestions?

Again this worked for a stand-alone project but not when I tried to integrate it into my webApp.

@rakkers
Copy link

rakkers commented Feb 14, 2021

I have now fixed the problem I was having by making sure that all projects in my solution were using the same version of System.ComponentModel.Annotations and that the re-direct was consistently applied in all projects.

@jenksguo
Copy link
Contributor

Hi @nmarkroberts thanks so much for sharing your solution and analysis. If you are base US, UK, AU, NZ please send me your T-shirt size and delivery address so I can send you some Xero developer goodies. :-)

@jenksguo
Copy link
Contributor

@rakkers Glad to know you were able to resolve this. :-D

@jenksguo
Copy link
Contributor

Closing this for now. Please re-open if there is an action on the SDK.

@kodeworks-git
Copy link

This has been tormenting me for several hours everyday over the last 3 days now. I have tried several variations of the binding redirect solution proposed by @nmarkroberts, @kanebullen and @MatthewSteeples but none have worked. Having only recently been unceremoniously introduced to the concept of binding redirects, I'm pretty much groping in the dark with this.

During my repeated installs/uninstalls of the Xero.NetStandard.OAuth2 package, however, I noticed one thing - there is no System.ComponentModel.Annotation V4.2.0 (see screenshot below).

image

Could it be that somewhere in the Xero.NetStandard.OAuth2 API there is a hard reference to a V4.2.0 that does not or no longer exists? @nmarkroberts suggested above that the fix should be implemented in the Xero.NetStandard.OAuth2 package itself and I would agree.

Any input that will help get us get past this and back to working on our actual solution would be appreciated.

@kanebullen
Copy link

@kodeworks-git May not help at all, but I found out the other day when dealing with another DLL hell, that if your web.config has a "xmlns" defined at the "configuration" level, that assembly bindings are ignored. So removing that may be worth playing with (assuming you're in a web environment)

@kodeworks-git
Copy link

Thanks @kanebullen for your suggestion . Unfortunately we're working on a desktop integration solution using the PKCE flow (we're implementing our own DLL hell!). I've made a note of it though for when we do have to implement a web-based integration.

@alincak
Copy link

alincak commented Jan 3, 2022

I have now fixed the problem I was having by making sure that all projects in my solution were using the same version of System.ComponentModel.Annotations and that the re-direct was consistently applied in all projects.

worked. thanks. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OAuth 2.0 Issues related to the OAuth 2.0 library Status: In Discussion
Projects
None yet
Development

No branches or pull requests

10 participants