We've observed that when we expose a WCF service which uses classes decorated with various xml serialisation attributes, despite the fact that we use the XmlSerializerFormat attribute on the interface any XmlRoot attribute on any of the operation's parameters gets completely ignored. The namespace of the parameters is always that of the service and not what we specify.
This is causing us problems as it does not seem to be backwards compatible with ASMX and also because we're using BizTalk, and need to have tighter control over the shape of the XML's exchanged.
A few questions then -
I've seen this post, but I don't believe it is relevant to my question -
As per Wagner Silveira's request - the contracts I used to test this are -
[ServiceContract(Namespace = "http://servicecontract"),
XmlSerializerFormat(Style = OperationFormatStyle.Document)]
public interface ITestService
{
[OperationContract]
MyOtherType MyTestMethod(MyType obj);
}
// Composite class for DCS and XMLS
[Serializable, XmlType, XmlRoot(Namespace = "http://datacontract")]
public class MyType
{
[XmlAttribute]
public string StringValue { get; set; }
}
// Composite class for DCS and XMLS
[Serializable, XmlType, XmlRoot(Namespace = "http://datacontract")]
public class MyOtherType
{
[XmlAttribute]
public string OtherStringValue { get; set; }
}
I assume you're using SOAP as the message format. In this case, the object you're serializing is not the root of the XML, the soap envelope is. So it makes sense that the XmlRoot would be ignored. By default WCF will create a message contract for you and name the response and it has the namespace of the service. What you can do is create your own message contract to have full control over SOAP.
Create the following two classes:
[MessageContract]
public class MyTestMethodRequest
{
[MessageBodyMember( Namespace = "http://datacontract" )]
public MyType MyType;
}
[MessageContract]
public class MyTestMethodResponse
{
[MessageBodyMember( Namespace = "http://datacontract" )]
public MyOtherType MyOtherType;
}
Then change the signature of your service operation to the following.
[OperationContract]
public MyTestMethodResponse MyTestMethod( MyTestMethodRequest request )
{
return new MyTestMethodResponse {
MyOtherType = new MyOtherType {
OtherStringValue = "bar"
}
};
}
Now if you example the SOAP messages you should see the following:
Request
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none"
s:mustUnderstand="1">http://servicecontract/TestService/MyTestMethod</Action>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyTestMethodRequest xmlns="http://servicecontract">
<MyType StringValue="foo" xmlns="http://datacontract" />
</MyTestMethodRequest>
</s:Body>
</s:Envelope>
Response
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyTestMethodResponse xmlns="http://servicecontract">
<MyOtherType OtherStringValue="bar" xmlns="http://datacontract" />
</MyTestMethodResponse>
</s:Body>
</s:Envelope>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With