Search code examples
c#wcfxml-attribute

WCF deserialization with XmlEnumAttribute


Enum is automatically deserialized by the WCF service.

[XmlType(Namespace = "http://rca.ws.emitere/2010-11/")]
public enum Animal
{
    [System.Xml.Serialization.XmlEnumAttribute("Cat name")]
    Cat,

    [System.Xml.Serialization.XmlEnumAttribute("Dog name")]
    Dog

}

Using

XmlElement(Form = XmlSchemaForm.Unqualified)]
    public Animal anim{ get; set; }

Can I set the default value, when no match is correct? Right now it generates a serialization error.

I want to return a validation message without changing the wsdl. The web service has several methods and for each of them one should return another message.


Solution

  • Unfortunatelly you are trapped in using enum in WCF contract. One option that can work for you is to change type of property anim to String and add other property attributed by XmlIgnore that will contain your desired value after deserialization is completed. Please remember that by this you might have to consider the same "value transfer" for serialization as well.

    Let's suppose anim property is contained in:

    public class Zoo
    {
        [XmlIgnore]
        public Animal? animAsEnum { get; set; }
    
        public string anim { get; set; }
    
        [OnDeserialized]
        private void OnDeserializedMethod(StreamingContext context)
        {
            Animal animAsEnum;
            if (Enum.TryParse(anim, out animAsEnum))
            {
                this.animAsEnum = animAsEnum;
            }
        }
    }
    

    How it works can be demonstrated as follows:

    [TestMethod]
    public void Zoo_Cateau()
    {
        string input = "<Zoo xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" "
            + "xmlns=\"http://schemas.datacontract.org/2004/07/UnitTestProject3\">"
            + "<anim>Cateau</anim></Zoo>";
    
        Zoo target = Deserialize<Zoo>(input);
        Assert.IsNotNull(target);
        Assert.AreEqual("Cateau", target.anim);
        Assert.IsNull(target.animAsEnum);
    }
    
    [TestMethod]
    public void Zoo_Cat()
    {
        string input = "<Zoo xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" "
            + "xmlns=\"http://schemas.datacontract.org/2004/07/UnitTestProject3\">"
            + "<anim>Cat</anim></Zoo>";
    
        Zoo target = Deserialize<Zoo>(input);
        Assert.IsNotNull(target);
        Assert.AreEqual("Cat", target.anim);
        Assert.AreEqual(Animal.Cat, target.animAsEnum);
    }
    

    Where Deserialize<T> method is taken from Using DataContractSerializer to serialize, but can't deserialize back