Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Mtom Encoding in WCF

4.93/5 (11 votes)
5 Aug 2013CPOL2 min read 69.1K  
Mtom encoding in WCF.
In this post we will cover
  • What is MTOM Encoding
  • MTOM Vs Text Encoding
  • Reasons to choose MTOM
  • Demo
MTOM (Message Transmission Optimization Mechanism) – WCF supports 3 encodings (in context of WCF, encoding means converting a WCF message (serialized XML InfoSet) into bytes) – Text, MTOM & Binary. All Http Bindings (Basic, WS, Dual, etc.) support Text / MTOM encoding, Text being the default one.

Why MTOM?
Problem with Text Encoding is it uses base 64 encoding format which can inflate the message size by 30%. This can be a heavy penalty while carrying large binary attachments.
On the other hand, MTOM avoids base 64 encoding for binary attachments keeping the overall size of message in control. Moreover, MTOM is based on open specifications & hence is largely interoperable.

Enough of theory... Let's do a demo to concretize the concept.

For this, i have created a simple WCF service. Below image will describe what we intend to do.






Contract :
namespace TestMTOM
{
    using System.Runtime.Serialization;
    using System.ServiceModel;

    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        Result GetData(string value);
    }

    [DataContract]
    public class Result
    {
        [DataMember]
        public string Message { get; set; }

        [DataMember]
        public byte[] FileContent { get; set; }
    };
}

Service Implementation:
namespace TestMTOM
{
    using System.IO;
    using System.ServiceModel.Activation;

    [AspNetCompatibilityRequirements
        (RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class Service1 : IService1
    {
        private byte[] FileToByteArray(string fileName)
        {
            byte[] buff = null;
            FileStream fs = new FileStream(fileName, 
                FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            long numBytes = new FileInfo(fileName).Length;
            buff = br.ReadBytes((int)numBytes);
            return buff;
        }

        public Result GetData(string value)
        {
            return new Result
                {
                    Message = string.Format("Hi {0}, File Received.", value),
                    FileContent = this.FileToByteArray(@"c:\sample.pdf")
                };
        }
    }
}

Configuration:
x<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    <bindings>
      <wsHttpBinding>
        <binding name="SecureHttpBinding"  <yellow>messageEncoding="Text"</yellow> closeTimeout="00:10:00" openTimeout="00:10:00" sendTimeout="00:10:00" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" />
          <security mode="None">
            <transport clientCredentialType="Windows" />            
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="Servicebehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <dataContractSerializer maxItemsInObjectGraph="2147483647" />          
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="Servicebehavior" name="TestMTOM.Service1">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="SecureHttpBinding" name="SecureHttp" contract="TestMTOM.IService1" />
        <endpoint address="mex" binding="mexHttpBinding" name="Mex" contract="IMetadataExchange" />
        <host>
          <timeouts closeTimeout="00:10:00" openTimeout="00:10:00" />
        </host>
      </service>
    </services>
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
        <directoryBrowse enabled="true" />
  </system.webServer>  
</configuration>

Client Code:
I have created a simple Windows Forms application shown below.

Code:
namespace MTOMClient
{
    using MTOMClient.MTOMSvc;

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            LblMessage.Text = string.Empty;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MTOMSvc.Service1Client client = new Service1Client();
            string name = tbName.Text;
            var result = client.GetData(name);
            LblMessage.Text = result.Message;
        }
    }
}
I executed client code and got the result, I tracked this call on fiddler. Observe the Highlighted parts of the response.

You can see that the binary content of the file is part of SOAP envelope. Now imagine a scenario where you need to log every call to your WCF service. Server will run into out of memory exception with in no time.

To separate the huge byte array of file content from the SOAP envelope, Mtom encoding has to be used. For this just change the below attribute value in <Binding> tag.
                           messageEncoding="Mtom"
Once the message encoding changed to Mtom, I executed the client and tracked the call on fiddler. Now look at the response.

Now, I will explain each part:
Content Type: multipart / related
This says that the response is divided into multiple parts and the huge array of bytes were separated from SOAP envelope and referred with blue color part highlighted in above screen shot.

<s:Envolope>
You can see that the SOAP envelope got closed in the same screenshot and the content is referred separately. Compare it with the earlier screenshot with "Text" message encryption, the <s:Envolope> tag has huge content inside , thus making it tough for logging.

<GetDataResult>
Represents the actual result in SOAP body.

<b:FileContent>
Represents the byte array of a huge PDF file. Thanks to Mtom encryption, now the content is separated, so that you can log the whole SOAP message thus making it easy for logging, and every aspect of the call can be tracked in this case.

Content-ID: <http://tempuri.org/1/635113188588698327>
Represents the Mtom encoded byte array generated from huge PDF file.

Now lets talk about size of the received message, which is a crucial aspect in performance and network perspective. The below image will speak for itself.
Thus we demonstrated the significant outcome of using Mtom encryption while using WCF services.

Code Sample :
Search for Mtom.zip in here.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)