Search code examples
c#wcfwsdlxml-serialization

XmlSerializer in WCF serialize wrong


I got some XSD:

<xs:complexType name="myFaultType">
    <xs:sequence>
        <xs:element name="type" type="mns:enumServiceException" />
        <xs:element name="code" type="xs:integer" />
        <xs:element name="message" type="xs:string" />
        <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" />
    </xs:sequence>
</xs:complexType>

<xs:element name="myFault" type="mns:myFaultType" />

<xs:simpleType name="enumServiceException">
    <xs:restriction base="xs:string">
        <xs:enumeration value="constraint" />
        <xs:enumeration value="objectNotFound" />
        <xs:enumeration value="permissionDenied" />
        <xs:enumeration value="runtime" />
        <xs:enumeration value="updateConflict" />
        <xs:enumeration value="versioning" />
    </xs:restriction>
</xs:simpleType>

XSD.exe generated this (code with my fixups):

[GeneratedCode("xsd", "2.0.50727.3038")]
[Serializable]
[DebuggerStepThrough]
[DesignerCategory("code")]
[XmlType(Namespace = "http://docs.oasis-open.org/messaging/200908/")]
[XmlRoot("myFault", Namespace = "http://docs.oasis-open.org/messaging/200908/", IsNullable = false)]
public sealed class myFaultType
{
    [XmlElement(Order = 1)]
    public enumServiceException type;

    [XmlElement(Order = 2, DataType = "integer")]
    public string code;

    [XmlElement(Order = 3)]
    public string message;

    [XmlElement(Order = 4)]
    public XmlElement[] any;
}

[GeneratedCode("xsd", "2.0.50727.3038")]
[Serializable]
[XmlType(Namespace = "http://docs.oasis-open.org/messaging/200908/")]
public enum enumServiceException
{
    constraint,
    objectNotFound,
    permissionDenied,
    runtime,
    updateConflict,
    versioning,
}

Contract:

    [XmlSerializerFormat]
    public interface IObjectService
    {
        [FaultContract(typeof(myFaultType))]
        DoSomeResponseMessage DoSome(DoSomeRequestMessage message);
    }

Problems:

1 - This is WSDL part generated by studio (Wrong ordering):

<xs:complexType name="myFaultType"><xs:sequence>
<xs:element name="any" nillable="true" type="q1:ArrayOfXmlElement"/>
<xs:element name="code" nillable="true" type="xs:string"/>
<xs:element name="message" nillable="true" type="xs:string"/>
<xs:element name="type" type="tns:enumServiceException"/></xs:sequence></xs:complexType>

2 - in my IErrorHandler in ProvideFault that code

var exception = new FaultException<myFaultType>(new myFaultType(), "fault reason");
var messageFault = exception.CreateMessageFault();
fault = Message.CreateMessage(version, messageFault, "http://URL/v1-0/Fault");

Generate that fault message (Wrong ordering, Some default namespaces instead of expected "http://docs.oasis-open.org/messaging/200908/"):

<s:Body>
<s:Fault>
  <faultcode>s:Client</faultcode>
  <faultstring xml:lang="ru-RU">fault reason</faultstring>
  <detail>
    <myFaultType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/SomeMyNamespace">
      <any xmlns:d6p1="http://schemas.datacontract.org/2004/07/System.Xml" i:nil="true" />
      <code>0</code>
      <message>repositoryId - invalid format</message>
      <type>invalidArgument</type>
    </myFaultType>
  </detail>
</s:Fault></s:Body>

What i do wrong?

Seems like WCF doesn't care about that XmlSerializer attributes.


Solution

  • I figured out what's the problem: by default WCF serialize faults with DataContractSerializer to change it to the XmlSerializer some property must be set as it says in Serializing Faults using XmlSerializer:

    [XmlSerializerFormat(SupportFaults=true)]