As you know WCF supports three types of message encodings (Encoding is the process of converting serialized object graph data into a format that can be transmitted over a network or saved to a file for later retrieval. Encoded data can be fed into a deserializer to hydrate the original object). Each encoding mechanism caters to different purpose but mostly decides the interoperability aspect of the service. They also produce different encoded output for the same logical data. In this post, I want to highlight the differences between these encoding types in terms of the actual payload they create for a given serialized object. In other words, we will see to what extent each of them bloats the original serialized object and which one is the least bloating.

WCF also supports three types of serializers:
XmlSerializer,
NetDataContractSerializer and
DataContractSerializer. Without getting into deep:
XmlSerializer provides the most customization options on the serialized XML and extensive support for XSD.
NetDataContractSerializer and
DataContractSerializer provide limited control over the generated (serialized) XML and limited support for XSD. For example, both the
DataContractSerializer versions serialize an object into element-only XML; you cannot for instance force a property to appear as an attribute. They also support versioning.
NetDataContractSerializer however scores better over
DataContractSerializer by providing high type fidelity by sharing assembly and type information in the serialization. This implies that both the service and client should have access to the same assembly containing the types exchanged in the WCF calls. Since most scenarios use (and also as the default)
DataContractSerializer, the rest of this article uses this serializer only.

 All right, back to encoding options. As said earlier, WCF has three types of encoding options: Text (plain XML), MTOM (Message Transmission Optimization Mechanism) and Binary. I am having a couple of simple data contracts with default settings/configurations applied to them:

using System.Collections.Generic;
using System.ServiceModel;


 //


[DataContract]
public class PersonInfo
{
    [DataMember]
    public string Name;
    [DataMember]
    public short Age;
    [DataMember]
    public char Gender;
    [DataMember]
    public List<Department> PreviousDepartments;
    [DataMember]
    public byte[] Photo = new byte[1000];
    public PersonInfo()
    {
        PreviousDepartments = new List<Department>();
        new Random().NextBytes(this.Photo);
    }
}

[DataContract]
public class Department
{
    [DataMember]
    public int DepartmentID;
    [DataMember]
    public string DepartmentName;
}

This small piece of code initializes an instance of
PersonInfo with three child complex types:

var pi = new PersonInfo() {Name="Susan Davis", Age=39, Gender='F'};
pi.PreviousDepartments.Add (new Department(){DepartmentID=1, DepartmentName="Sales"});
pi.PreviousDepartments.Add (new Department(){DepartmentID=3, DepartmentName="Administration"});
pi.PreviousDepartments.Add (new Department(){DepartmentID=3, DepartmentName="Engineering"});


Nothing special! Let us see how the text (XML) serializer encodes this object with the following code:

MemoryStream ms = new MemoryStream ();
XmlDictionaryWriter tw = XmlDictionaryWriter.CreateTextWriter (ms);
DataContractSerializer dcs = new DataContractSerializer (typeof (PersonInfo));
dcs.WriteObject (tw, pi);
tw.Flush ();
DumpStream (ms);


DumpStream() is a simple helper method to dump the encoded object into the console window:

private static void DumpStream (MemoryStream s)
{
    Console.BackgroundColor = ConsoleColor.Yellow;
    Console.ForegroundColor = ConsoleColor.Red;
    Console.WriteLine ("Content length: {0} bytes", s.Length);
    Console.ResetColor ();
    s.WriteTo (Console.OpenStandardOutput ());
    Console.WriteLine ();
}


And the output looks like this:

WCF Text Encoding

Note that the default behavior of plain text encoding is to base64-encode any binary data. Let us see the output of MTOM encoding for the same object instance:

tw = XmlDictionaryWriter.CreateMtomWriter (ms = new MemoryStream (), Encoding.UTF8, Int32.MaxValue, "");
dcs.WriteObject (tw, pi);
tw.Flush ();
DumpStream (ms);


 WCF MTOM Encoding

Note that the MTOM is basically a multi-part MIME message where binary data is base64-encoded and streamed into a separate section of the message. The original XML just makes a reference to this section.

WCF MTOM Encoding

However, MTOM encoding creates multi-part messages only if the base64-encoded data size exceeds 1024 bytes. Otherwise, it simply keeps the base64 content inline and as a result brings down the overall message size (280 bytes less in this case) as there is no MIME header and additional section reference.

WCF MTOM Encoding

Let us see the binary encoding now:

tw = XmlDictionaryWriter.CreateBinaryWriter (ms = new MemoryStream ());
dcs.WriteObject (tw, pi);
tw.Flush ();
DumpStream (ms);


 Produce the following output:

WCF Binary Encoding

As you can see, binary encoding produces the smallest wire size compared to the other two encodings. Note that it also lacks the standard XML headers and it is a bit difficult to make out the actual content too unlike the other two. I heard a couple of beeps as well when this message was shown J Actually, MTOM by nature is supposed to perform better compared to text but this wasn’t the case in the above test scenario (1024 bytes of binary data). So, I went further and did few more iterations using the same code but increasing the binary array size in each iteration to see how each of these encoding do with increase binary data. As expected, after a point, MTOM performed better than text and came near (but no close) to binary encoding.

WCF Encoder Comparison

This graph is just an illustration to show and compare the performance of the three encoding options in WCF. Microsoft may change their implementation in future to bring the differences smaller. To summarize:

  1. Text encoding gives support for plain XML and provides the widest interoperability compared to others.
  2. Binary is efficient and produces smallest message size among the others. This should be considered when both the service and consumer are WCF-based.
  3. MTOM is good for objects containing binary data but it still outputs plain XML for normal object properties. This also provides significant interoperability because W3C has standardized MTOM.

Comments are closed.

Post Navigation