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

Weird TypeLoadException that only shows up in UWP? #2438

Closed
Joebeazelman opened this issue Dec 10, 2017 · 33 comments
Closed

Weird TypeLoadException that only shows up in UWP? #2438

Joebeazelman opened this issue Dec 10, 2017 · 33 comments
Assignees
Labels

Comments

@Joebeazelman
Copy link

I have several assemblies containing WCF web services. They all work perfectly in my .NET Framework 4.6.2 MSTEST project. When I execute the same functions in my UWP application, I get the following exception for one of the projects, but not the others:

System.TypeLoadException
HResult=0x80131522
Message=Type 'generatedProxy_2' from assembly 'ProxyBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is attempting to implement an inaccessible interface.
Source=
StackTrace:

Interestingly, I click on the exception for more information, I get the following:

	$exception	error CS0012: The type 'FaultException<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.ServiceModel.Primitives, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.	

It appears to be a different exception altogether. Which exception is correct and why the divergence? Also, why didn't the primitive types carry its references.

@Joebeazelman
Copy link
Author

What's going on here? I added a reference to the latest version 4.4.1 of System.ServiceModel.Primitives along with auto binding redirects and I still get the same message.

@mlacouture
Copy link
Member

Hi @Joebeazelman! let me try to understand your scenario just to make sure we are on the same page:

  1. When you say 'assemblies containing WCF web services' do you mean 'service references'? I ask because UWP is a client platform so web services cannot be hosted using this platform.

  2. When you say 'execute de same functions in my UWP app', do you mean you recompiled your .NET Framework libraries in the UWP? I ask this because WCF in the UWP supports only a limited set of features from the .NET Framework version. This means the proxy code generated for the .NET Framework may not work in the UWP.

  3. Can you provide more details about your projects, in particular the one that is failing? are all of them created from the UWP library template? if you can provide a narrowed-down repro project that we can look at, it would be very helpful.

The exception you are getting is definitely confusing, we need more data to be able to troubleshoot the issue.

thank you!
Miguel Lacouture

@Joebeazelman
Copy link
Author

Joebeazelman commented Dec 12, 2017

Hi Miguel,

Thanks for all your help and responses. Let me address each of your questions:

  1. The assemblies are all client proxies built using .NET Standard 2.0. The UWP app is the main application and serves as a front end with references to the different client proxies. There's only one proxy giving me the exception and it makes a call to FaultException. The other ones use the standard single message FaultException.

  2. When I say execute the same function, I mean the UWP app references all of the client proxies and calls them. The one client that throws the FaultException does it only when called from the UWP app and no where else. Specifically, it has the following attribute on its operation contract:

[System.ServiceModel.FaultContractAttribute(typeof(ServiceReference1.ErrorDetailType[]), Action="http://whoop.com/webservices/WhoopBinding/v1.1", Name="Errors", Namespace="http://www.whoop.com/XMLSchema/XOLTWS/Error/v1.1")]

  1. This is the most information I can offer, but I have nailed it down to FaultException. Zhenlan claims Microsoft.NETCore.UniversalWindowsPlatform v6.0.4 package already has the shim. Somehow, the shim isn't being applied to FaultException.

@Joebeazelman
Copy link
Author

I want to add this as well:

1> Encountered conflict between 'Reference:C:\Users\mbarr.nuget\packages\microsoft.netcore.universalwindowsplatform\6.0.5\ref\uap10.0.15138\System.ServiceModel.Primitives.dll' and
'Reference:C:\Users\mbarr.nuget\packages\system.servicemodel.primitives\4.4.1-servicing-25917-01\ref\netcore50\System.ServiceModel.Primitives.dll'.

Choosing 'Reference:C:\Users\mbarr.nuget\packages\microsoft.netcore.universalwindowsplatform\6.0.5\ref\uap10.0.15138\System.ServiceModel.Primitives.dll' because AssemblyVersion '4.2.1.0' is greater than '4.1.1.0'.

@mlacouture
Copy link
Member

mlacouture commented Dec 13, 2017

adding @zhenlan
@Joebeazelman thank you for the extra information provided.

@zhenlan
Copy link
Member

zhenlan commented Dec 14, 2017

Zhenlan claims Microsoft.NETCore.UniversalWindowsPlatform v6.0.4 package already has the shim. Somehow, the shim isn't being applied to FaultException.

If all your assemblies are compiled against NS2.0, you should not need the shim. The shim is for the assemblies compiled against full framework to work on UWP/.NET Core.

The conflicting error about System.ServiceModel.Primitives.dll is expected. You should not reference system.servicemodel.primitives\4.4.1-servicing-25917-01 package, which is a servicing release. The system.servicemodel.primitives shipped in microsoft.netcore.universalwindowsplatform\6.0.5 is a higher version one and has more APIs.

Adding @mconnew to see if he has any suggestions to the issue you have.

@Joebeazelman
Copy link
Author

Joebeazelman commented Dec 14, 2017 via email

@Joebeazelman
Copy link
Author

Can I get some feedback on this? Is there a workaround?

@mconnew
Copy link
Member

mconnew commented Dec 15, 2017

Sorry I didn't reply sooner, I've been very busy on another time critical issue. I think the original message is the key here. We have a build step which generates a proxy class which implements your service interface. This is the type which gets instantiated when you call ChannelFactory.CreateChannel(). The runtime exception is saying that the service interface is not accessible to the proxy class that implements it. Is your service interface defined as either internal or private? When not running the native compilation toolchain, we use a different mechanism which creates the proxy class at runtime using refemit and this doesn't have the same accessibility limitations so code which works fine running managed could have this problem when natively compiled.

@Joebeazelman
Copy link
Author

@mconnew Thanks. This has solved the issue. I originally suspected the service interface to be the issue. I always generate my service interfaces as internal, since there is no reason to use them directly. So I shouldn't have turned on this otherwise innocent option.

So it turns out Microsoft summons demon code in WCF. Emitting and executing additional proxy code outside the statically generated one is worthy of a Bozo Prize. Clearly, the responsible programmer passed the whiteboard interview, but failed to the piss cup test.

In, other words, THIS IS A BUG! Shame on you Microsoft!

@mconnew
Copy link
Member

mconnew commented Dec 16, 2017

Can you suggest a different way to have ChannelFactory<TChannel>.CreateChannel() return an object which implements the interface TChannel without code generation in a UWP app? The constraints are there's no refemit (used in .Net Core) and no .Net remoting (used in full .Net framework).

@zhenlan zhenlan added this to the S129 milestone Jan 8, 2018
@zhenlan
Copy link
Member

zhenlan commented Jan 8, 2018

According to @mconnew, this is likely due to multi-file feature in UWP that the user-defined service interface and the toolchain-generated dispach proxy are in two different assemblies.

@zhenlan zhenlan added the UWP label Jan 20, 2018
@zhenlan zhenlan modified the milestones: S129, S130 Jan 20, 2018
@zhenlan zhenlan modified the milestones: S130, S131 Feb 2, 2018
@zhenlan zhenlan self-assigned this Feb 2, 2018
@zhenlan
Copy link
Member

zhenlan commented Feb 11, 2018

I gave this a try with a UWP app created from template with VS 2017 v15.6.0 preview 4 and settings below

  • TargetPlatformMinVersion v10.0.16299.0
  • Microsoft.NETCore.UniversalWindowsPlatform v6.0.7

Then in the UWP app, I added WCF client proxy using "Add Service Reference" (note, this is not WCF connected services) against a WCF service that is also created just out of the template with settings below

  • Add Service Reference -> Advanced -> Access level for generated classes -> Internal

The issue does not repro when the UWP app is built in either debug or release mode. Next, I will try to build the WCF proxy in a separate library project.

@zhenlan
Copy link
Member

zhenlan commented Feb 25, 2018

Update: the issue does not repro when the WCF proxy is in a separate library project (either netstandard2.0 library or UWP library).

@zhenlan zhenlan modified the milestones: S131, S132 Feb 25, 2018
@Lxiamail Lxiamail modified the milestones: S132, S133 Mar 16, 2018
@Lxiamail Lxiamail modified the milestones: S133, S134 Apr 6, 2018
@zhenlan
Copy link
Member

zhenlan commented Apr 14, 2018

I remember there is a setting to enforce multi-file feature in UWP project, but I cannot find it handy. This is what we should try next.

@morganbr do you happen to know the UWP setting to enable multi-file feature?

@Lxiamail
Copy link
Member

@morganbr Do you have any input?

@Lxiamail Lxiamail modified the milestones: S134, S135 May 11, 2018
@morganbr
Copy link
Contributor

Sorry, I must have missed this the first time. In UWP, multi-file is on by default, but the msbuild property is <UseDotNetNativeSharedAssemblyFrameworkPackage>true</UseDotNetNativeSharedAssemblyFrameworkPackage> (true means multi-file, false means single-file).

@morganbr
Copy link
Contributor

That said, the exceptions above sound more like CoreCLR exceptions than .NET Native exceptions. I wonder if this is a Debug or Release issue.

@mconnew
Copy link
Member

mconnew commented May 11, 2018

@morganbr , an assembly for the proxy is only generated when compiled to .NET Native. If this was running with CoreCLR, it would be using an in-memory temporary assembly created using RefEmit. I don't believe the original exception message matches what you would see with a refemit generated temporary assembly. Would you get a TypeLoadException from Ref Emit code on CoreCLR?

@zhenlan zhenlan removed their assignment May 21, 2018
@morganbr
Copy link
Contributor

I've confirmed it's CoreCLR. ProxyBuilder is used in the RefEmit implementation. That also matches an accessibility error since .NET Native never checks accessibility.

@Lxiamail Lxiamail modified the milestones: S135, S138 Jul 5, 2018
@Lxiamail
Copy link
Member

Lxiamail commented Jul 6, 2018

@morganbr Is there a way to implement an internal Interface using RefEmit?

@Lxiamail Lxiamail modified the milestones: S138, 3.0 Jul 6, 2018
@morganbr
Copy link
Contributor

morganbr commented Jul 6, 2018

Sorry, I don't know much about RefEmit. @atsushikan?

@ghost
Copy link

ghost commented Jul 6, 2018

TypeBuilder is still subject to the normal accessibility rules.

@mconnew
Copy link
Member

mconnew commented Jul 11, 2018

@atsushikan, on .Net Framework we using transparent proxies with remoting to create our WCF proxy. This can dispatch calls for any interface method regardless of accessibility. Could we do something with a naming convention when creating the dynamic assembly/dynamic module along with InternalsVisibleToAttribute? Is there a way to have InternalsVisibleTo specify an assembly which is dynamically generated? I.e. someone has an internal interface MyNameSpace.IMyInterface so they add an InternalsVisibleTo attribute specifying a name which is derived from this, (e.g. "MyNameSpace.IMyInterface.DispatchProxy") which would enable the dynamic code to access the internal interface?

@ghost
Copy link

ghost commented Jul 11, 2018

Is there a way to have InternalsVisibleTo specify an assembly which is dynamically generated?

I don't know but it's easy to set up an experiment to find out.

@JKennedy24
Copy link

Is there any fix/workaround for this issue?

@Lxiamail
Copy link
Member

@JKennedy24 Is making the contract interface to be public a reasonable work around for you?

@JKennedy24
Copy link

@Lxiamail When you talk about the Contract Interface are you talking about the service side or client side?
I have checked both sides and they all seem to be already public

@JKennedy24
Copy link

This is the exception I am seeing when using my WCF client class on UWP:

System.IO.FileNotFoundException: 'Could not load file or assembly 'System.ServiceModel.Http, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.'

@Lxiamail
Copy link
Member

@JKennedy24 If the client side contract is already public, which sounds like a different issue than the original reported issue on this thread. #3088 may be closer. #3088 looks like a UWP project reference transit problem. UWP team is doing investigation. It would be helpful to confirm if you can share the repro project.

@Lxiamail
Copy link
Member

Lxiamail commented Nov 8, 2018

@atsushikan, have you gotten chance to try out @mconnew's suggestion?

@Lxiamail
Copy link
Member

Close this issue for now. Please feel free to reopen it if @mconnew's suggestion doesn't work for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants