Serialization in WCF–Part I

Posted: September 10, 2011 in .NET, WCF
Tags: ,

In general, when we work with WCF services Serialization/Deserialization is taken care by the framework under the hood.We rarely bother about what serializer is used and how it works.But it’s important to understand this as the message payload generated is fully controlled by serializer you use. So a better understanding of the serialization process /techniques and it’s limitations will help us to design the services better.

WCF uses the System.Runtime.Serialization.DataContractSerializer class for this purpose.The code snippet below uses DataContractSerializer to serialize Plain CLR Object.

class Program 
    { 
        static void Main(string[] args) 
        { 
            Customer c = new Customer() { FirstName = "Sankarsan", LastName = "Bose", Address = "404/6 NSC BOSE ROAD" }; 
            DataContractSerializer ds = new DataContractSerializer(typeof(Customer)); 
            using(var m = new MemoryStream()) 
            { 
                ds.WriteObject(m,c); 
                m.Seek(0,SeekOrigin.Begin); 
                using (var sr = new StreamReader(m)) 
                { 
                    Console.WriteLine(sr.ReadToEnd()); 
                } 
                
            } 
                   Console.Read(); 
        } 
    } 
    public class Customer 
    { 
        public String FirstName { get; set; } 
        public String LastName { get; set; } 
        public String Address { get; set; }

    }


The output will be the following XML string.

<Customer xmlns="http://schemas.datacontract.org/2004/07/SerializationDemo" xmlns:i="'>http://www.w3.org/2001/XMLSchema-instance">

<Address>404/6 NSC BOSE ROAD</Address>

<FirstName>Sankarsan</FirstName>

<LastName>Bose</LastName>

</Customer>

We need to note the following points:

a) The output is XML format

b) A Plain CLR object(POCO) without any additional decoration(attributes) is serialized with Type Name and Properties as XML Elements (This is called inferred data contracts)

c) The xmlns attribute by default is http://schemas.datacontract.org/2004/07/<<CLR Namespace Name>>

d) The ordering of the properties/fields is alphabetically sorted.

e) The XML output does not contain any additional information CLR Datatypes.This is the reason we need to provide the type information while we instantiate the Serializer.

Now if we need to have more fine grained over the serialization output we need to have some mechanism to provide additional inputs to the serializer regarding how we can want to customize our output. The System.Runtime.Serialization.DataContractAttribute and System.Runtime.Serialization.DataMemberAttribute provides the same.

We have used these attributes in the Customer class as shown below:

[DataContract(Name="customer",Namespace="http://sankarsanbose.com/Customer")] 
    public class Customer 
    { 
        [DataMember(Name="firstname",Order=1)] 
        public String FirstName { get; set; } 
        [DataMember(Name = "lastname", Order = 2)] 
        public String LastName { get; set; } 
        [DataMember(Name = "address", Order = 3)] 
        public String Address { get; set; }

    }


The XML output produced is as shown below:

<customer xmlns="http://sankarsanbose.com/Customer" xmlns:i="'>http://www.w3.org/2001/XMLSchema-instance">

<firstname>Sankarsan</firstname>

<lastname>Bose</lastname>

<address>404/6 NSC BOSE ROAD</address>

</customer>

Here we have altered the name of the XML Elements, Namespace and ordering of the elements.

We will play around a little bit with this attributes and let’s remove DataMemberAttribute from one of the properties and make another one private.

[DataContract(Name="customer",Namespace="http://sankarsanbose.com/Customer")] 
public class Customer 
{ 
    [DataMember(Name="firstname",Order=1)] 
    public String FirstName { get; set; } 
    [DataMember(Name = "lastname", Order = 2)] 
    private String LastName { get; set; } 
    public String Address { get; set; }

} 

As the xml output below shows the property(Address) without the DataMemberAttribute is not serialized and the private attribute is serialized with a default NULL value.

<customer xmlns="http://sankarsanbose.com/Customer" xmlns:i="'>http://www.w3.org/2001/XMLSchema-instance">
<firstname>Sankarsan</firstname>
<lastname i:nil="true"/>
</customer>

The default value can be controlled through the EmitDefaultValue parameter of the DataMember attribute.This is true by default and can be turned off as shown below:

[DataContract(Name="customer",Namespace="http://sankarsanbose.com/Customer")]
public class Customer
{
    [DataMember(Name="firstname",Order=1)]
    public String FirstName { get; set; }
    [DataMember(Name = "lastname", Order = 2,EmitDefaultValue=false)]
    private String LastName { get; set; }
    public String Address { get; set; }

}

So the serialized data now no longer emits the lastname with Null value:

<customer xmlns="http://sankarsanbose.com/Customer" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<firstname>Sankarsan</firstname>
</customer>

This post covers the basics and in the next post we will take a deeper look into the DataContractSerializer class.

Comments
  1. Serame says:

    Hi Sankarsan, i’m working on a piece where i’m creating a Dynamic Link Library using Reflection for WCF and i have a problem defining a Custom Attributes [DataContract] [DataMember] which will
    be Type dmaType = typeof(DataMemberAttribute);

    Please help!

  2. Ibrahim says:

    Waiting for next part……

  3. radhe says:

    very good even for sr developer

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.