We have an existing SOAP web service interface that we want to implement using WCF for a new application. This seems to work fine except for one small detail. The XML namespace of the return type of a function must be different than the XML namespace of the web service itself. And for the life of me, I can't get it to work.
I've recreated the same problem with a small sample project. The WCF interface:
[XmlSerializerFormat]
[ServiceContract(Namespace = "urn:outer-namespace")]
public interface IService1
{
[OperationContract]
MyClass DoStuff(int value);
}
[Serializable]
public class MyClass
{
[XmlElement(ElementName = "DataString")]
public string MyString { get; set; }
}
The web service implementation:
public class Service1 : IService1
{
public MyClass DoStuff(int value)
{
return new MyClass { MyString = "Wooh!" };
}
}
A response from this webservice is then serialized as: (Omitting SOAP stuff)
<DoStuffResponse xmlns="urn:outer-namespace">
<DoStuffResult>
<DataString>Wooh!</DataString>
</DoStuffResult>
</DoStuffResponse>
But we want the <DoStuffResult> to be of xmlns="urn:inner-namespace".
I've tried adding a [return: XmlElement(...)] on the interface function or the web service function, but that doesn't take. Also an [XmlType] or [XmlRoot] on the MyClass class definition doesn't work.
Does anyone have an idea how to change the serialized XML namespace (or element name) of the object that is the return value of a WCF web service function?
Windows Communication Foundation (WCF) can use two different serialization technologies to turn the data in your application into XML that is transmitted between clients and services, a process called serialization. By default WCF uses the DataContractSerializer class to serialize data types. This serializer supports the following types:
When deserializing XML, the serializer uses the XmlReader and XmlWriter classes. It also supports the XmlDictionaryReader and XmlDictionaryWriter classes to enable it to produce optimized XML in some cases, such as when using the WCF binary XML format. WCF also includes a companion serializer, the NetDataContractSerializer.
Windows Communication Foundation (WCF) includes a new serialization engine, the DataContractSerializer. The DataContractSerializer translates between .NET Framework objects and XML, in both directions.
Using the XmlSerializer Class. Windows Communication Foundation (WCF) can use two different serialization technologies to turn the data in your application into XML that is transmitted between clients and services, a process called serialization.
After days of searching and trying dozens of recommended solutions; I was finally able to get WCF to stop forcing a wrapper container name of appending Result
to the name of the web service method. The trick was to add the following decorator attribute to the web service interface:
[return:MessageParameter(Name = "whatIWantItNamed")]
This attribute should be placed/located directly after the [OperationContract]
attribute (and just before the actual method stub) in the interface.
(I also needed to add an XmlSerializerFormat
attribute to all of the ServiceContract
and OperationContract
attributes.)
Define namespaces with the XML Serialisation (or, better) Data Contract definition attributes.
e.g. with XML Serialisation:
[Serializable, XmlRoot(namespace="http://example.com/eg1")]
public class MyClass {
[XmlElement(ElementName = "DataString")]
public string MyString { get; set; }
}
e.g. with Data Contract serialisation:
[DataContract(Namespace="http://example.com/eg2")]
public class MyClass {
[DataMember]
public string MyString { get; set; }
}
EDIT
Based on the first comment, the above won't work, because the desire is to set the namespace on the SOAP wrapper around the message, not on the message itself.
OperationContractAttribute
offers no control of namespaces, and I can't see any other WCF attributes at a method level.
Two possibilities: (1) You may have enough control by dropping a level of abstraction and using a Message Contract. (2) Get the current WSDL for the service (using svcutil.exe
), manually adjusting it to get the namespaces you want, and then using svcutil.exe
again to generate the code, and look at the resulting code.
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