Sunday, March 17, 2013

WCF- Serialization and Deserialization



WCF  use  DataContractSerializer serialization engine to  translates between .NET Framework objects and XML.

WCF also includes a companion serializer, the NetDataContractSerializer. The NetDataContractSerializer is similar to the BinaryFormatter and SoapFormatter serializers because it also emits .NET Framework type names as part of the serialized data.

Windows Communication Foundation supports three serializers: 

  • ·         XmlSerializer,
  • ·         DataContractSerializer
  • ·         NetDataContractSerializer

Interface
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WCF_Serialization
{
    [ServiceContract]
    public interface ICustomerDetails
    {
      
        [OperationContract]
        CustomerDetails GetCustomers();

     }

    [DataContract]
    public class CustomerDetails
    {
        private int _Cid;
        private string _CName;
        private DateTime  _CDob;

        
        public int CustomerID
        {
            get { return _Cid; }
            set { _Cid = value; }
        }

        [DataMember]
        public string CustomerName
        {
            get { return _CName; }
            set { _CName = value; }
        }

        [DataMember]
        public DateTime CustomerDOB
       {
            get { return _CDob; }
            set { _CDob = value; }
        }
    }
}


Service  :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Xml;
using System.IO;
namespace WCF_Serialization
{
   
    public class Service1 : ICustomerDetails
    {
        CustomerDetails _obj;
        public CustomerDetails GetCustomers()
        {
            _obj = new CustomerDetails();      
            _obj.CustomerID   = 1001;
            _obj.CustomerName  = "Virat Kohli";
            _obj.CustomerDOB  = DateTime.Now.AddYears(-30);

            _obj = new CustomerDetails();
            _obj.CustomerID = 1002;
            _obj.CustomerName = "joe Root";
            _obj.CustomerDOB = DateTime.Now.AddYears(-30);


DataContractSerializer ds = new DataContractSerializer(typeof(CustomerDetails));

            // This part is user to Serialize Funddetail Class /

            XmlWriterSettings settings = new XmlWriterSettings() { Indent = true };

         
            using (XmlWriter w = XmlWriter.Create(@"C:\Users\vikas.kumar\Desktop\WCF Experiments\WCF-Serialization\WCF-Serialization\cuatomerdetails.xml", settings))
                ds.WriteObject(w, _obj);
            System.Diagnostics.Process.Start(@"C:\Users\vikas.kumar\Desktop\WCF Experiments\WCF-Serialization\WCF-Serialization\cuatomerdetails.xml");



            // Deserialize the data and read it from the instance.
            FileStream fs = new FileStream(@"C:\Users\vikas.kumar\Desktop\WCF Experiments\WCF-Serialization\WCF-Serialization\cuatomerdetails.xml", FileMode.Open);
            XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
            DataContractSerializer ser = new DataContractSerializer(typeof(CustomerDetails));

            CustomerDetails dser = (CustomerDetails)ser.ReadObject(reader, true);
            reader.Close();
            fs.Close();


            return _obj;
        }
      
    }

}


Client  :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Xml;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {

            ServiceReference1.CustomerDetailsClient obj = new ServiceReference1.CustomerDetailsClient();
            obj.GetCustomers();


        }
    }
    
}

Outpt:

<?xml version="1.0" encoding="UTF-8"?>
-<Customer xmlns="http://schemas.datacontract.org/2004/07/WCF_Serialization" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<CustomerAutoID>1002</CustomerAutoID>
  <CustomerFullName>joe Root</CustomerFullName>
  <DateOfBirth>1983-03-11T15:37:48.2931458+04:00</DateOfBirth>
  </Customer>



Ordering of elements is alphabetic order 


Test 1 : 

Change data contract members : 
Here we have altered the name of the XML Elements, Namespace and ordering of the elements.

   [DataContract(Name = "Customer", Namespace = "http://wcftest1.com/Customer")]
    public class CustomerDetails
    {
        private int _Cid;
        private string _CName;
        private DateTime  _CDob;

        [DataMember(Name = "CustomerAutoID", Order = 3)]
        public int CustomerID
        {
            get { return _Cid; }
            set { _Cid = value; }
        }

        [DataMember(Name = "CustomerFullName", Order = 1)]       
        public string CustomerName
        {
            get { return _CName; }
            set { _CName = value; }
        }

        [DataMember(Name = "DateOfBirth", Order = 2)]      
        public DateTime CustomerDOB
        {
            get { return _CDob; }
            set { _CDob = value; }
        }
    }


Output :


<?xml version="1.0" encoding="UTF-8"?>
-<Customer xmlns="http://wcftest1.com/Customer" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <CustomerFullName>joe Root</CustomerFullName>
  <DateOfBirth>1983-03-11T15:37:48.2931458+04:00</DateOfBirth>
  <CustomerAutoID>1002</CustomerAutoID>
</Customer>


Test 2 : 
In this test we are removing  DataMember attribute  from customer name property and adding two more  data members  Country and Salary  with default value null.
The EmitDefaultValue parameter of the DataMember attribute country set to false

  [DataContract(Name = "Customer", Namespace = "http://wcftest1.com/Customer")]
    public class CustomerDetails
    {
        private int _Cid;
        private string _CName;
        private DateTime  _CDob;
        //private double _sal;
        private string _country;

        [DataMember(Name = "CustomerAutoID", Order = 2)]
        public int CustomerID
        {
            get { return _Cid; }
            set { _Cid = value; }
        }
      
        public string CustomerName
        {
            get { return _CName; }
            set { _CName = value; }
        }

        [DataMember(Name = "DateOfBirth", Order = 1)]
        public DateTime CustomerDOB
        {
            get { return _CDob; }
            set { _CDob = value; }
        }



        [DataMember(Name = "CustomerCountry", Order = 3, EmitDefaultValue=false)]
        public string Country =null;

        [DataMember(Order = 4)]
        public string Salary = null;

    }


Output:
In output we can see CustomerName properity is not serialized because it is not declared as datamember

<?xml version="1.0" encoding="UTF-8"?>
-<Customer xmlns="http://wcftest1.com/Customer" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <DateOfBirth>1983-03-11T16:01:27.3231002+04:00</DateOfBirth>
  <CustomerAutoID>1002</CustomerAutoID>
  <Salary i:nil="true"/>
</Customer>


Types Supported by the Data Contract Serializer

Data contract types. These are types to which the DataContractAttribute attribute has been applied

All public fields, and properties with public get and set methods are serialized, unless you apply the IgnoreDataMemberAttribute attribute to that member.

Collection types. These can be regular arrays of types, or collection types, such as ArrayList and Dictionary. The CollectionDataContractAttribute attribute can be used to customize the serialization of these types, but is not required. 

Enumeration types. Enumerations, including flag enumerations, are serializable. Optionally, enumeration types can be marked with the DataContractAttribute attribute, in which case every member that participates in serialization must be marked with the EnumMemberAttribute attribute. Members that are not marked are not serialized. For more information, see Enumeration Types in Data Contracts.

.NET Framework primitive types. The following types built into the .NET Framework can all be serialized and are considered to be primitive types: Byte, SByte, Int16, Int32, Int64, UInt16, UInt32, UInt64, Single, Double, Boolean, Char, Decimal, Object, and String.

Other primitive types. These types are not primitives in the .NET Framework but are treated as primitives in the serialized XML form. These types are DateTime, DateTimeOffset, TimeSpan, Guid, Uri, XmlQualifiedName, and arrays of Byte.

XmlSerializer :

Let’s take above example and serialize class with XmlSerializer.

Service :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Xml;
using System.IO;
namespace WCF_Serialization
{
   
    public class Service1 : ICustomerDetails
    {
       
        public CustomerDetails GetCustomers()
        {
            CustomerDetails _obj;
             OrderDetails _obj2;

             _obj2 = new OrderDetails();  
            _obj2.orderID = 3001;
            _obj2.Item = "Cloths";


            _obj = new CustomerDetails();      
            _obj.CustomerID   = 1001;
            _obj.CustomerName  = "Virat Kohli";
            _obj.CustomerDOB  = DateTime.Now.AddYears(-30);
            _obj.customerorder = _obj2;
         


            _obj2 = new OrderDetails();
            _obj2.orderID = 3002;
            _obj2.Item = "Electronic";

            _obj = new CustomerDetails();
            _obj.CustomerID = 1002;
            _obj.CustomerName = "joe Root";
            _obj.CustomerDOB = DateTime.Now.AddYears(-30);
            _obj.customerorder = _obj2;
        
System.Xml.Serialization.XmlSerializer ds = new System.Xml.Serialization.XmlSerializer(typeof(CustomerDetails));


            XmlWriterSettings settings = new XmlWriterSettings() { Indent = true };

         
            using (XmlWriter w = XmlWriter.Create(@"C:\Users\vikas.kumar\Desktop\WCF Experiments\WCF-Serialization\WCF-Serialization\cuatomerdetails.xml", settings))
                ds.Serialize(w, _obj);
            System.Diagnostics.Process.Start(@"C:\Users\vikas.kumar\Desktop\WCF Experiments\WCF-Serialization\WCF-Serialization\cuatomerdetails.xml");

            return _obj;
        }      
    }
}

Output :

<?xml version="1.0" encoding="UTF-8"?>
-<CustomerDetails xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  -<customerorder>
    <orderID>3002</orderID>
    <Item>Electronic</Item>
  </customerorder>
<CustomerID>1002</CustomerID>
<CustomerName>joe Root</CustomerName>
<CustomerDOB>1983-03-13T11:26:24.2903215+04:00</CustomerDOB>
</CustomerDetails>

Here we can see that it includes the Customer Name too which is the public property.In case of DataContractSerializer this property is not serialized.

 

NetDataContractSerializer :

DataContractSerializer uses data contract names.

NetDataContractSerializer outputs full .NET Framework assembly and type names in the serialized XML. 

This means that the known types mechanism is not required with the NetDataContractSerializer because the exact types to be deserialized are always known.

Using the NetDataContractSerializer is similar to using the DataContractSerializer, with the following differences:

  • The constructors do not require you to specify a root type. 
  • we can serialize any type with the same instance of the NetDataContractSerializer.
  • The constructors do not accept a list of known types
  • The constructors accept a parameter called assemblyFormat of the FormatterAssemblyStyle that maps to the AssemblyFormat property. As discussed previously, this can be used to enhance the versioning capabilities of the serializer. This is identical to the FormatterAssemblyStyle mechanism in binary or SOAP serialization.
  • The constructors accept a StreamingContext parameter called context that maps to the Context property. You can use this to pass information into types being serialized. This usage is identical to that of the StreamingContext mechanism used in other System.Runtime.Serialization classes.
  • The Serialize and Deserialize methods are aliases for the WriteObject and ReadObject methods. These exist to provide a more consistent programming model with binary or SOAP serialization.
NetDataContractSerializer ds = new NetDataContractSerializer();

when we use NetDataContractSerializer, you no longer have to supply type information ahead of time, as illustrated here:

Since the .NET type information is found in the XML, you don't need to specify the .NET type when deserializing either.



Output:
<?xml version="1.0" encoding="UTF-8"?>-<Customer xmlns="http://wcftest1.com/Customer" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Assembly="WCF-Serialization, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" z:Type="WCF_Serialization.CustomerDetails" z:Id="1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">  <CustomerAutoID>1001</CustomerAutoID> <DateOfBirth>1983-03-13T12:10:13.3143215+04:00</DateOfBirth> -<Orderdetails z:Id="2" xmlns:d2p1="http://schemas.datacontract.org/2004/07/WCF_Serialization">
    <d2p1:Item z:Id="3">Cloths</d2p1:Item>
    <d2p1:orderID>3001</d2p1:orderID>
  </Orderdetails>
</Customer>




Message Encoding :

Service :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Xml;
using System.IO;
namespace WCF_Serialization
{
   
    public class Service1 : ICustomerDetails
    {
       
        public CustomerDetails GetCustomers()
        {
            CustomerDetails _obj;
             OrderDetails _obj2;

             _obj2 = new OrderDetails();  
            _obj2.orderID = 3001;
            _obj2.Item = "Cloths";

            _obj = new CustomerDetails();      
            _obj.CustomerID   = 1001;
            _obj.CustomerName  = "Virat Kohli";
            _obj.CustomerDOB  = DateTime.Now.AddYears(-30);
            _obj.customerorder = _obj2;         


            System.ServiceModel.Channels.Message message = System.ServiceModel.Channels.Message.CreateMessage(System.ServiceModel.Channels.MessageVersion.Soap11WSAddressing10,
        "http://www.ServiceContract.com/Samples/RPCExample/Name", _obj, new DataContractSerializer(typeof(CustomerDetails)));
  


         using (FileStream fs = new FileStream(@"C:\Users\vikas.kumar\Desktop\WCF Experiments\WCF-Serialization\WCF-Serialization\binary.bin", FileMode.Create))
        {
            using (XmlDictionaryWriter writer =
                   XmlDictionaryWriter.CreateBinaryWriter(fs))
            {
                message.WriteMessage(writer);
            }
        }


            System.Diagnostics.Process.Start(@"C:\Users\vikas.kumar\Desktop\WCF Experiments\WCF-Serialization\WCF-Serialization\binary.bin");


             using (FileStream fs = File.OpenRead(@"C:\Users\vikas.kumar\Desktop\WCF Experiments\WCF-Serialization\WCF-Serialization\binary.bin"))
            {
                using (XmlDictionaryReader reader =
                  XmlDictionaryReader.CreateBinaryReader(fs, XmlDictionaryReaderQuotas.Max))
                {
                    using (System.ServiceModel.Channels.Message message1 = System.ServiceModel.Channels.Message.CreateMessage(
                        reader, 1024, System.ServiceModel.Channels.MessageVersion.Soap11WSAddressing10))
                    {
                        // deserialize Person object from XML
                        CustomerDetails name = message1.GetBody<CustomerDetails>(
                            new DataContractSerializer(typeof(CustomerDetails)));
                    }
                }
            }

            return _obj;
        }
   }

}

Output:

 


Enumeration Types in Data Contracts







Custom collection serialization :

Inteface 

using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;

namespace WCF_DataContract_CollectionType
{
  [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        PurchaseOrder Getorder();
    }

    [DataContract(Name = "CustomerPurchase")]
    public class PurchaseOrder
    {
        [DataMember(Order=1)]
        public string customerName;

        [DataMember(Order = 2)]
        public ICollection<Item>   Items_IcollectionItems;

       [DataMember(Order = 3)]
        public List<Item> Items_List;

        [DataMember(Order = 4)]
        public string[] review;
    }

    public class Item
    {
        public int itemid;
        public string ItemName;
    }
}


Service
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Xml;
using System.IO;

namespace WCF_DataContract_CollectionType
{
    public class Service1 : IService1
    {

        public PurchaseOrder Getorder()
        {
            PurchaseOrder _obj;
            _obj = new PurchaseOrder();
            Item _obj2;
           
            string[] R = { "Review1", "review2" };

            List<Item> objlst = new List<Item>();   
            ICollection<Item> objIcol = new Collection<Item>();  

            _obj2 = new Item();  
            _obj2.itemid  = 3001;
            _obj2.ItemName = "Mobiles";
           
            _obj2.itemid = 3002;
            _obj2.ItemName = "LCD";
                    
            objIcol.Add(_obj2);
            objlst.Add(_obj2); 

           
            _obj.customerName = "Customer1";
            _obj.Items_IcollectionItems = objIcol;
            _obj.Items_List = objlst;
            _obj.review = R;
           
            DataContractSerializer ds = new DataContractSerializer(typeof(PurchaseOrder));
            XmlWriterSettings settings = new XmlWriterSettings() { Indent = true };
            using (XmlWriter w = XmlWriter.Create(@"C:\Users\vikas.kumar\Desktop\WCF Experiments\WCF-Serialization\WCF-Serialization\cuatomerdetails.xml", settings))
                ds.WriteObject(w, _obj);
            System.Diagnostics.Process.Start(@"C:\Users\vikas.kumar\Desktop\WCF Experiments\WCF-Serialization\WCF-Serialization\cuatomerdetails.xml");


            // Deserialize the data and read it from the instance.
            FileStream fs = new FileStream(@"C:\Users\vikas.kumar\Desktop\WCF Experiments\WCF-Serialization\WCF-Serialization\cuatomerdetails.xml", FileMode.Open);
            XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
            DataContractSerializer ser = new DataContractSerializer(typeof(PurchaseOrder));
            PurchaseOrder p = (PurchaseOrder)ser.ReadObject(reader);

            reader.Close();
            fs.Close();


            return _obj;
        }
      
   
    }
}


Client :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {

            ServiceReference1.Service1Client obj = new ServiceReference1.Service1Client();
            obj.Getorder();
            Console.ReadLine();  

        }
    }
}


Output

<?xml version="1.0" encoding="UTF-8"?>
-<CustomerPurchase xmlns="http://schemas.datacontract.org/2004/07/WCF_DataContract_CollectionType" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <customerName>Customer1</customerName> -<Items_IcollectionItems>
    -<Item>
      <ItemName>LCD</ItemName>
      <itemid>3002</itemid>
    </Item>
  </Items_IcollectionItems>
-<Items_List>
    -<Item>
      <ItemName>LCD</ItemName>
      <itemid>3002</itemid>
    </Item>
  </Items_List> -<review xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <d2p1:string>Review1</d2p1:string>
    <d2p1:string>review2</d2p1:string>
  </review>
</CustomerPurchase>






4 comments :

  1. your articles are good...but writing them day-by-day/weekly...as a schedule then which is so good.

    what is next article...Lavi?

    ReplyDelete
    Replies
    1. HI,
      Thanks
      Yes need to organised on schedule basis may be later.

      Next I think I will work on WCF transactions and Channel Factory,Asynchronous WCF Service Operations etc

      Delete
  2. thanks for my above reply...Lavi

    WCF Async operations and Channel Factory articles are good.

    what is next article ....Live.

    ReplyDelete
  3. what is today article Lavi... by viswanadh

    ReplyDelete