Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET WCF serialization issues

The situation: system A is supposed to expose SOAP 1.2 web service for system B to call. In order for A to know what the message looks like, B sent an XSD to A describing the contents of the message. A generated the stubs using the .NET xsd.exe tool, created the simple webservice around this and the job was done.

However; when B calls this webservice, A refuses to serialize the SOAP/XML content to the generated proxy class instances. I realize this must be down to the way the serialization is defined on the webservice side on system A, but have been unable to locate exactly what is going wrong.

What the message from B looks like (anonymized) - FAILS:

<ns2:Set_Out xmlns:ns2="http://a.a/1.0" xmlns:ns1="http://b.b/1.0" xmlns:ns0="http://c.c">
<Context xmlns="">
    <Foo>test</Foo>
    <Bar>test</Bar>
    ...
</Context>

What a test message from a test client (based on the WSDL) looks like - WORKS:

<Set_Out xmlns="http://a.a/1.0">
<Context xmlns:b="http://schemas.datacontract.org/2004/07/x.x" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <b:Foo>TEST</b:Foo>
    <b:Bar>test</b:Bar>
    ...
</Context>

When the webservice built by A receives the messages from B, it doesn't serialize the message at all. The objects of the proxy (for instance Context) are null. When it receives the messages from a test client, everything is generated correctly.

The serialization attributes on the proxy:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://a.a/1.0")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://a.a/1.0", IsNullable=false)]
[System.ServiceModel.MessageContract]
public partial class Set_Out {
    [System.Xml.Serialization.XmlElementAttribute(Namespace="http://a.a/1.0", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]    [System.ServiceModel.MessageBodyMember(Order=0)]
    public ContextType Context;
    ...

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://a.a/1.0")]
public partial class ContextType {
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string Foo;

Things I find odd:

  1. When generating the WSDL for this service, the WSDL adds its own namespaces to the WSDL definition (xmlns:b in the example above, for instance).
  2. The WSDL doesn't respect the unqualified annotations defined in the proxy, and makes everything qualified.

I've tried various combinations of annotations, but nothing seems to help; the messages from B aren't correctly deserialized to the proxies generated by A. Any ideas/pointers/help would be much appreciated!

like image 389
tmbrggmn Avatar asked Apr 20 '11 13:04

tmbrggmn


People also ask

What is the serialization in .NET how is it affecting to .NET programming?

Serialization is a process of converting an object into a stream of data so that it can be is easily transmittable over the network or can be continued in a persistent storage location. This storage location can be a physical file, database or ASP.NET Cache.

What is serialization in WCF?

Windows Communication Foundation (WCF) uses the DataContractSerializer as its default serialization engine to convert data into XML and to convert XML back into data. The DataContractSerializer is designed to serialize data contract types.

Which namespace is used for serialization in WCF?

By default WCF uses the DataContractSerializer class to serialize data types.

Which classes are responsible for message serialization in WCF?

Use the DataContractSerializer with default settings for serialization.


2 Answers

In a typical case of "ask the question, solve it yourself 5 minutes later" I've managed to solve my problem.

The issue was that, apparently, when using WCF .NET uses a default serializer for the classes involved in the data contract. This default serializer (I believe it's DataContractSerializer) apparently doesn't really allow much in the way of configuration. I had to tell WCF to use XmlSerializer to serialize the message. To do this, I had to add the [XmlSerializerFormat()] annotation to the service contract interface (apparently it's meant to work on operations as well). Example:

[ServiceContract(Namespace = "http://a.a/1.0")]
[XmlSerializerFormat()]
public interface IMyWebService
{
    [OperationContract()]
    void DoStuff(Set_Out message);
}

After adding the [XmlSerializerFormat()] annotation, the WSDL changed significantly (proper namespaces) and the messages are serialized correctly.

Forum post that set me on the right track: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/c7fede29-56c2-4ff3-bd02-48e3e0b2cec1/

like image 85
tmbrggmn Avatar answered Sep 18 '22 13:09

tmbrggmn


(this is actually a comment, but it can't fit)

Try adding the system.diagnostics to your web.config to find out more information about errors:

    <system.diagnostics>
    <trace autoflush="true" />
    <sources>
        <source name="System.ServiceModel"
                switchValue="Information, ActivityTracing"
                propagateActivity="true">
            <listeners>
                <add name="sdt"
                    type="System.Diagnostics.XmlWriterTraceListener"
                    initializeData= "C:\MyLog.svclog" />
            </listeners>
        </source>
    </sources>
    </system.diagnostics>

You can view the svclog using C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SvcTraceViewer.exe (or similar). Add this to both services (different log filenames of course), and see which one fails, and exactly why.

I would suspect that the serialization is OK, but some binding/setting of the service causes the call to fail.

like image 40
veljkoz Avatar answered Sep 22 '22 13:09

veljkoz