I recently ran into a situation where the WSDL was altered to allow for xs:any in part of the expected SOAP body for a WCF service I am implementing in support of the project.  I have handled this situation before in WSE 3.0 and ASMX web services and was anxious to find out how WCF would handle it. 

When working with large XML models such as the National Information Exchange Model (NIEM) it is becoming common to use xs:any for parts of messages because the schemas that support the message structure are too complex to include in the WSDL.  For the large data sharing projects I work on at the state and federal level this is pretty much the standard.  Just about everyone has a "Payload" element that is of type xs:any.

With WSE 3.0 and ASMX web services .NET would convert the xs:any part of the SOAP body to a System.Array containing a single item of type System.Xml.XmlText.  I was only able to discover this because I was provided a Java based client to send requests to our service so that I could debug and see what types were coming across.  Somehow when I sent the same requests from .NET the xs:any was interpreted as a System.String and I did not have to do any further work to get the data I needed from that part of the message.

When I learned I would be in that same situation with WCF I started searching to find any documentation on what might possibly happen.  To my dismay I could not locate any via searches on MSDN, Google, etc. 

I ran some tests using a .NET WCF client and used message tracing to capture the raw soap message.  Upon inspection I noticed that the .NET client was appending xsi:type="xsd:string" on the element that was of type xs:any per the WSDL.  Also the first item in that tag was the XML declaration tag.  When my WCF service received that request it treated that element as a string and capture the raw string XML.

After searching I decided to use SoapUI to run the tests.  I installed SoapUI and began a test project.  I took the raw SOAP message captured in my .NET test and pasted that into the body of the test data window in SoapUI.  While testing I discovered that in SoapUI you need to remove the <soap:Header> element if one is included in the trace data you are using (it was causing errors with the ws-addressing headers).  Once I did that I was able to get some messages to hit the service. 

Test cases:

Soap Body included: <Payload xsi:type="xsd:string"><?xml version="1.0" encoding="UTF-8"?> … xml content …</Payload>
Result: InvalidOperationException – Error in XML document at Line {N} Position {N}

Soap Body included: <Payload xsi:type="xsd:string"> … xml content …</Payload>
Result: InvalidOperationException – Error in XML document at Line {N} Position {N}

Soap Body included: <Payload> … xml content …</Payload>
Result: Payload property on incoming message received as a System.Array containing one item that was of type System.Xml.XmlElement

What I found was very interesting was that when I used the exact trace output from the message created by my .NET client it received an exception when I sent it with SoapUI.  I tried a few variations of escaping characters to no avail.  There must be some type of escaping that .NET does in order to facilitate sending the xs:any portion of the message as a string, I just couldn’t guess them.

I’m still curious as to how the .NET WCF Client is encoding the content in the xs:any element to get it to pass those deserialization checks.  If anyone has any thoughts, leave me a comment.

Technorati Tags: ,,