Consuming a WCF Service from a “Windows Runtime Component” project type is a limited supported scenario particularly with the usage of XmlSerializer.
Background:
Consider the following scenario. You are developing a Windows Store app and need to consume a WCF Service. The most common approach of consuming a WCF service and using the .NET framework is to create a managed Windows Store app based on the C# or VB.Net language.
Additionally, Visual Studio 2012 also provides you an option to create a “Windows Runtime Component” project type template in the File, New Project dialog.
The “Windows Runtime Component” project type gives developers a flexibility of creating a library that can be consumed from a Windows Store app regardless of the programming language that the final Windows Store app is written in. For example, your main app can be written in HTML/WinJS and it can still use this component.
The main purpose of creating this type of project is for the usage scenario just explained above where HTML/WinJS does not have any in-built support to use the WCF functionality of the .NET framework.
Problem:
To consume a WCF Service from the “Windows Runtime Component” project type, you need to “Add Service Reference” to your project and point it to where the WCF Service definition resides.
When such a Service Reference is added to the project that uses the XmlSerializer, you will notice compilation warnings and errors immediately after the service generation:
“Custom tool warning: A service reference file with public XML Serialization types has been added to a WinMD project. Public types in a WinMD project have to conform to the Windows Runtime rules set; otherwise, it might result in build errors. You need to update the service reference file in order to avoid the errors.”
Additionally you might also get extra warnings that read like this:
“Custom tool warning: Endpoint 'XYZ' at address '<Endpoint Address>' is not compatible with Windows Store apps. Skipping... <Project location>\Reference.svcmap”
To check why the warnings are thrown, you can open the Reference.cs file that gets added under the “Reference.svcmap” folder under the added ServiceReference. Over there you will observe that there are types that have been created like the following:
public partial class ClassName : object, System.ComponentModel.INotifyPropertyChanged {….
When you now try compiling the project, the compiler will fail reporting the following:
“Exporting unsealed types is not supported. Please mark type '<ClassName>' as sealed”
To remove the compilation errors, you now add the “sealed” keyword to your class in the Reference.cs file to make it WinRT compatible. This will cause the compilation errors to go away, however there will be issues during runtime.
At runtime, when you call a WebMethod of that WCF service from your app that requires the ClassName parameter to be passed in as an input variable, calling the method may throw a runtime error/ exception. The runtime error will look similar to the following message:
“There was an error in serializing body of message : 'There was an error generating the XML document.'. Please see InnerException for more details.”
If you check the InnerException value of the nested exceptions, you will notice error messages like this:
“There was an error generating the XML document”
and
“The request is not supported. (Exception from HRESULT:0x80070032)”
The reason the exceptions are thrown is because the XmlSerializer cannot get enough information to serialize the input type due to the fact that the class is marked sealed. And you cannot un-mark the class
without the “sealed” keyword otherwise the project will not even compile.
The summary of this issue is that consuming a WCF Service from the “Windows Runtime Component” project type is a limited supported scenario particularly with the usage of XmlSerializer.
Solution:
If you do want to consume such a WCF Service that makes use of the XmlSerializer, the ideal solution is to create a Windows Store app and use the Add Service Reference functionality to add the reference directly in the app without trying to embed this in a Windows Runtime Component.
Using a “Windows Runtime Component” project type is not the way to go.
If you want to consume a WCF Service from a HTML/WinJS project type, the ideal solution would be to change your service to a REST based approach that will make the service even more flexible in terms of usage.
Comments are welcome, both below and on twitter: #WSDevSol.