git clone https://toreaurstad@bitbucket.org/toreaurstad/wcfixmlserializabledemo.git
The source code is here: WcfIXmlSerializableDemo
The core of the serialization is done implementing the interface IXmlSerializable. The following class serves as a demonstration:
using System.Xml; using System.Xml.Schema; using System.Xml.Serialization; namespace CustomWcfSerialization.Common { // Use a data contract as illustrated in the sample below to add composite types to service operations. [XmlRoot("Animal", Namespace ="http://schemas.toreaurstad.no/2018/08")] public class Animal : IXmlSerializable { public Animal() { } bool _isBipedal; public bool IsBipedal { get { return _isBipedal; } set { _isBipedal = value; } } string _name; public string Name { get { return _name; } set { _name = value; } } public XmlSchema GetSchema() { return null; } public void ReadXml(XmlReader reader) { reader.MoveToContent(); Name = reader.GetAttribute("Name"); reader.ReadStartElement(); IsBipedal = bool.Parse(reader.ReadElementString("IsBipedal") == "Yes" ? "true" : "false"); reader.ReadEndElement(); } public void WriteXml(XmlWriter writer) { writer.WriteAttributeString("Name", Name); writer.WriteElementString("IsBipedal", IsBipedal ? "Yes" : "No"); } } }The serialized request and response from WCF now is changed from the default serialization of DataContractSerializer, to not only support XML attributes - but also represent booleans as a custom boolean where true and false is exchanged with "Yes" and "No".
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body>
<GetAnimalsResponse xmlns="http://tempuri.org/">
<GetAnimalsResult xmlns:a="http://schemas.datacontract.org/2004/07/CustomWcfSerialization.Common" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Animal Name="Rex"><IsBipedal>No</IsBipedal></a:Animal>
<a:Animal Name="Bubbles"><IsBipedal>Yes</IsBipedal>
</a:Animal>
</GetAnimalsResult> </GetAnimalsResponse></s:Body></s:Envelope>
Note though, that even we used special values for boolean values in our sample ("Yes" and "No"), it was possible to deserialize this by implementing the deserialization in the ReadXml method of our WCF service entity class Animal. This image shows that Visual Studio is able to deserialize the data into objects properly even that the XML presents data that is not directly compatible by .NET:
This is done by manually parsing the data retrieved from WCF like this:
IsBipedal = bool.Parse(reader.ReadElementString("IsBipedal") == "Yes" ? "true" : "false");You can quickly end up with much code if there is much code you want to serialize in a specific manner. It is possible use .NET reflection, generics and the [KnownType] argument for this in case you want to support this is a more generic manner. I will look into this in a future article.