A Java shop vendor we're collaborating with needs us (a .NET shop) to provide a RESTful service conforming to a WSDL they've sent us. There are several differences between the XML we're returning and what the vendor expects. Is my process fundamentally wrong, or is there just a difference in the way Java and .NET do serialisation?
My process:
The contract-first idea is new to me, but is covered well in posts like this. So armed with a little knowledge I've run the WSDL and associated .XSDs through SvcUtil.exe to generate C# (some relevant excerpts below), and I'm using these types as the return types for my service.
I've also tried generating the code using wsdl.exe
and xsd.exe
, but neither significantly changed the outcome.
The differences:
- Additional levels appear in my XML. In mine, there is sometimes an XML entity corresponding to the property name (e.g. "Code") and inside it there's an XML element corresponding to the type of the property (e.g. "CodeType"). The vendor is expecting only one level: "Code".
- Namespaces are different.
- What the vendor expects as an attribute ("codeValue") appears as an element.
- Null properties are included in my XML.
Results and code excerpts:
The vendor expects the service to return messages looking like this:
<?xml version="1.0" encoding="UTF-8"?>
<gms:GetClassificationResponse xmlns:gms="http://vendor.com/metadata/cms/services/integration/gms" xmlns:class="http://vendor.com/metadata/model/classification" xmlns:core="http://vendor.com/metadata/model/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://vendor.com/metadata/cms/services/integration/gms ../gms_services.xsd">
<class:ClassificationVersion>
<class:Code codeValue="01">
<Name core:type="Preferred">Northland Region</Name>
<class:Code codeValue="001">
<Name core:type="Preferred">Far North District</Name>
<class:Code codeValue="500206">
<Name core:type="Preferred">North Cape</Name>
</class:Code>
<class:Code codeValue="500207">
<Name core:type="Preferred">Houhora</Name>
</class:Code>
<!-- Truncated -->
</class:Code>
<class:Code codeValue="002">
<Name core:type="Preferred">Whangarei District</Name>
<!-- Children omitted -->
</class:Code>
<!-- Truncated -->
</class:Code>
<class:Code codeValue="02">
<Name core:type="Preferred">Auckland Region</Name>
<!-- Children omitted -->
</class:Code>
<!-- Truncated -->
</class:ClassificationVersion>
</gms:GetClassificationResponse>
We're producing results like this:
<GetClassificationResponseType xmlns="http://schemas.datacontract.org/2004/07/metadata.cms.services.integration.gms" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ClassificationVersion>
<actionField>ADD</actionField>
<actionFieldSpecified>false</actionFieldSpecified>
<anyAttrField xmlns:a="http://schemas.datacontract.org/2004/07/System.Xml" i:nil="true"/>
<descriptionField i:nil="true"/>
<detailField>full</detailField>
<idField i:nil="true"/>
<itemsField xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true"/>
<lastUpdateField>0001-01-01T00:00:00</lastUpdateField>
<lastUpdateFieldSpecified>false</lastUpdateFieldSpecified>
<nameField i:nil="true"/>
<uriField i:nil="true"/>
<isPreferredField>false</isPreferredField>
<itemField i:nil="true"/>
<validFromField>0001-01-01T00:00:00</validFromField>
<validFromFieldSpecified>false</validFromFieldSpecified>
<validToField>0001-01-01T00:00:00</validToField>
<validToFieldSpecified>false</validToFieldSpecified>
<Code>
<CodeType>
<actionField>ADD</actionField>
<actionFieldSpecified>false</actionFieldSpecified>
<anyAttrField xmlns:a="http://schemas.datacontract.org/2004/07/System.Xml" i:nil="true"/>
<descriptionField i:nil="true"/>
<detailField>full</detailField>
<idField>Whangarei</idField>
<itemsField xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true"/>
<lastUpdateField>0001-01-01T00:00:00</lastUpdateField>
<lastUpdateFieldSpecified>false</lastUpdateFieldSpecified>
<nameField>
<ContextualStringType>
<anyField/>
<isStructuredField>true</isStructuredField>
<actionField>ADD</actionField>
<actionFieldSpecified>false</actionFieldSpecified>
<anyAttrField xmlns:a="http://schemas.datacontract.org/2004/07/System.Xml" i:nil="true"/>
<langField i:nil="true"/>
<typeField>Preferred</typeField>
</ContextualStringType>
</nameField>
<uriField i:nil="true"/>
<Code>
<CodeType>
<actionField>ADD</actionField>
<actionFieldSpecified>false</actionFieldSpecified>
<anyAttrField xmlns:a="http://schemas.datacontract.org/2004/07/System.Xml" i:nil="true"/>
<descriptionField i:nil="true"/>
<detailField>full</detailField>
<idField>Springs Flat</idField>
<itemsField xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true"/>
<lastUpdateField>0001-01-01T00:00:00</lastUpdateField>
<lastUpdateFieldSpecified>false</lastUpdateFieldSpecified>
<nameField>
<ContextualStringType>
<anyField/>
<isStructuredField>true</isStructuredField>
<actionField>ADD</actionField>
<actionFieldSpecified>false</actionFieldSpecified>
<anyAttrField xmlns:a="http://schemas.datacontract.org/2004/07/System.Xml" i:nil="true"/>
<langField i:nil="true"/>
<typeField>Preferred</typeField>
</ContextualStringType>
</nameField>
<uriField i:nil="true"/>
<Code/>
<category i:nil="true"/>
<codeValue>502001</codeValue>
<level xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true"/>
</CodeType>
And some of the generated code
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://mtna.us/metadata/cms/services/integration/gms")]
[DataContract]
public partial class GetClassificationResponseType
{
private ClassificationVersionType classificationVersionField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "http://mtna.us/metadata/model/classification", Order = 0)]
[DataMember]
public ClassificationVersionType ClassificationVersion
{
get
{
return this.classificationVersionField;
}
set
{
this.classificationVersionField = value;
}
}
}
...
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://vendor.com/metadata/model/classification")]
public partial class ClassificationVersionType : ObjectVersionType
{
private LevelType1[] levelField;
private CodeType[] codeField;
private bool isViewField;
private string basisField;
public ClassificationVersionType()
{
this.isViewField = false;
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Level", Order = 0)]
public LevelType1[] Level
{
get
{
return this.levelField;
}
set
{
this.levelField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Code", Order = 1)]
public CodeType[] Code
{
get
{
return this.codeField;
}
set
{
this.codeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
[System.ComponentModel.DefaultValueAttribute(false)]
public bool isView
{
get
{
return this.isViewField;
}
set
{
this.isViewField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")]
public string basis
{
get
{
return this.basisField;
}
set
{
this.basisField = value;
}
}
}