简体   繁体   中英

WCF - Serialize/Deserialize boolean values as yes/no instead of true/false?

I'm writing a WCF web service, that serializes to and deserializes from an XML document. The XML file is used as a communication mechanism between an ERP and my .Net web service. The issue I'm facing is that I can't control the output of the ERP which is sending yes/no as the logical value that needs to be deserialized to a bool variable in my service.

I'm using DataContractSerializer with DataContract and DataMember decorations.

DataContractSerializer ser = new DataContractSerializer(typeof(Order));
Order GenerateOrder = (Order)ser.ReadObject(readDoc.CreateReader());

How can I deserialize yes/no to a bool property?

Boolean is a native .NET type, and .NET serialize it with native xsd:boolean defined in XML Schemas. So no, you can not serialize/deserialize a Boolean to Yes/No.

An alternative solution, you can define a custom enumeration and customize its serialization behavior with EnumMember Tags.

[DataContract]
public enum MyBoolean
{
    [EnumMember(Value = "No")]
    False,

    [EnumMember(Value = "Yes")]
    True
}

if you are using Yes, No for enumeration value, you can even write like this :

[DataContract]
public enum MyBoolean
{
    [EnumMember]
    No,

    [EnumMember]
    Yes
}

Using DataContract(s) will in most cases be sufficient, but custom serialization is desirable in interoperability scenarios. Though .NET does not use "Yes" and "No" for boolean values, maybe other platform / languages do. Therefore, you must make use of other serialization methods in WCF.

Consider implementing the IXmlSerializable interface of your data contract, this interface lets you both control serialization and deserialization at a low level.

Consider this example of a POCO that is used in a WCF service:

   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");
    }

}

Note that this class does not use [DataContract] attribute, instead it implements IXmlSerializable. After running a client against a WCF operation returning a list of this type Animal, we get the following serialized content (note that we here on the wire / response can use "Yes" as boolean values inspecting with Fiddler:

<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">


NoYes

Concerning IXmlSerializable - Note that the ReadXml method will take care of deserializing the object(s) and WriteXml method will take care of serializing the object(s). The GetSchema method can in most cases return null.

I have prepared a small demo project with a Visual Studio solution showing how this can be done here:

git clone git@bitbucket.org:toreaurstad/wcfixmlserializabledemo.git

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM