Workaround for accessing some ASMX services from Silverlight 4

On this blog we normally talk about building and accessing WCF services, since that is the recommended way to build services for Silverlight. However, we continue to support ASMX services using the familiar “Add Service Reference” feature.

Just recently some folks trying to talk to the ASMX services that SharePoint 2010 exposes brought an interesting issue to my attention. You would hit this issue if you were accessing SharePoint’s userprofileservice.asmx, but more generally you could hit this with any ASMX service that uses known types with Guid/char (for example the operation signature returns Object, but you actually return a Guid/char from within the operation).

When you hit this issue, you get the following exception as Silverlight tries to deserialize the service response:

System.ServiceModel.Dispatcher.NetDispatcherFaultException was unhandled by user code. The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter https://tempuri.org/:HelloWorldResponse. The InnerException message was 'Error in line 1 position 268. Element 'https://tempuri.org/:HelloWorldResult' contains data of the 'https://microsoft.com/wsdl/types/:guid' data contract. The deserializer has no knowledge of any type that maps to this contract. Add the type corresponding to 'guid' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'.  Please see InnerException for more details.

(Same goes for https://microsoft.com/wsdl/types/:char)

The error is causes by the fact that ASMX has a slightly different schema for the Guid and char types, which is currently not supported in Silverlight. We are looking at addressing this as soon as possible.

As a workaround, we can use the message inspectors feature that we introduced in Silverlight 4. The attached sample shows how to implement a message inspector can be added to the client when you are talking to an ASMX service. It processes every incoming message and adjusts the way char and Guid are represented, which results in WCF understanding those types correctly.

If you reuse the classes defined in the attached solution, all you need to do is add the new behavior to your generated proxy, like so:

 ServiceReference1.WebService1SoapClient proxy = new ServiceReference1.WebService1SoapClient();
            
// add behavior here
proxy.Endpoint.Behaviors.Add(new AsmxBehavior());
            
proxy.HelloWorldCompleted += new EventHandler<ServiceReference1.HelloWorldCompletedEventArgs>(proxy_HelloWorldCompleted);
proxy.HelloWorldAsync();

Download the solution here

Hope this helps,

-Yavor Georgiev

Program Manager, WCF