Click here to Skip to main content
12,635,237 members (23,735 online)
Click here to Skip to main content
Add your own
alternative version

Stats

82.3K views
1K downloads
30 bookmarked
Posted

CompactMessageEncoder

, 4 Sep 2007 Ms-PL
Rate this:
Please Sign up or sign in to vote.
The CompactMessageEncoder compresses messages transparently on the communication channel. Hence, lowers the network usage.

Introduction

There are many articles about how WCF works, so I'll skip that part in this article. The purpose of this piece of code is to enable the user to compress the data transferred between machines using the WCF. (For simplicity, I am using the term WCF instead of referring to specific components.)

When the WCF is used to communicate between two entities, it creates a channel of communication to transfer and then transfers messages. The messages contain the data of requests and responses. WCF uses special encoders to translate the request and responses data into an array of bytes.

The CompactMessageEncoder hooks into the channel on both sides (Client & Server). When a message is transferred, the encoder compresses it on the sending side and decompress it on the receiving side, hence it is transparent.

Background

My drive to implement such an encoder was the need to transfer a big file (XML format) from one machine to another, where the connection has a speed limit.

I decided to do this with WCF for simplicity (After the transfer, there were more things to do). I didn't want to write a special function that compresses on one side and uncompresses on the other, but rather configure the channel itself to do this. This way the compression can be reused on any contract.

After picking and poking in the Internet, I found out that writing a message encoder is the simplest way. The real problem was how to write a message encoder, since the MSDN doesn't have any example (at least I didn't find any). Any example I found was out of date since they were written before the WCF was finally released. However these examples gave me some firm ground of how to write a message encoder.

My implementation is based on an example that I got installed on my machine, but I don't know its origin. I found it at C:\Program Files\Microsoft SDKs\WinFX\samples\Allsamples\Indigo\TechnologySamples\Extensibility\
Channels\MessageEncoder\Compression\CS.
The example is exactly what I wanted to have in the first place, unfortunately it doesn't work. It is written for previous versions of WCF and includes interfaces and classes that no longer exist. From this example, I got the knowledge of how to compress and uncompress the message. I also noticed that the implementation had two minor bugs, so I fixed them.

I had some help from Nicholas Allen's blog at http://blogs.msdn.com/drnick/archive/2006/05/09/592933.aspx. However, it doesn't contain code on how to add the message encoder to the configuration file.

I also used the Reflector to see how other message encoders work such as:

System.ServiceModel.Channels.BinaryMessageEncoderFactory.BinaryMessageEncoder.

How It Works

The idea of the compact message encoder is to hook the sending and receiving of messages on the channel and compress them on the sender and then decompress them on the receiver. To implant the message encoder, a binding element is added into a customBinding.

Since the compression doesn't have to do the encoding itself, it uses another message encoder to do this for it, for example, the BinaryMessageEncoder.

Normal Service Method Execution

Sender side:

  1. A method is called in code.
  2. The method and its parameters are serialized into a SOAP message.
  3. The message encoder serializes the message into a bytes array.
  4. The bytes array are sent via the transport layer.

Receiver side:

  1. The transport layer receives a bytes array.
  2. The message encoder deserialized the bytes array into a message.
  3. The method and its parameters are deserialized into a SOAP message.
  4. The real method is called.

When the compact message encoder is added, the method call is changed a bit:

Sender side:

  1. A method is called in code.
  2. The method and its parameters are serialized into a SOAP message.
  3. The compact message encoder lets its inner message encoder to serialize the message into a bytes array.
  4. The compact message encoder compresses the bytes array into a second bytes array.
  5. The bytes array are sent via the transport layer.

Receiver side:

  1. The transport layer receives bytes array.
  2. The compact message encoder decompresses the bytes array into a second bytes array.
  3. The compact message encoder let its inner message encoder to deserialize the second bytes array into a message.
  4. The method and its parameters are deserialized into a SOAP message.
  5. The real method is called.

The compact message encoder is divided to several classes:

CompactMessageEncoder - This class provides the message encoder implementation.

CompactMessageEncoderFactory - This class is responsible to provide the Compact message encoder instance.

CompactMessageEncodingBindingElement - This is the class that participates in the binding stack of the channel.

CompactMessageEncodingElement - This is the class that enables the message encoder to be added via the application configuration file.

Compression

The CompactMessageEncoder uses the GZip compression which is implemented within the .NET Framework. This is implemented with System.IO.Compression.GZipStream.

How To Use

Add Reference to the CompactMessageEncoder.dll

Before changing the app.config, you must add a reference to the CompactMessageEncoder.dll. This must be done on both Client and Server applications.

Server config Change

This is an example of app.config before adding the compact message encoder:

<?xml version="1.0" encoding="utf-8" ?>
<configuration> 
    <system.serviceModel> 
        <services> 
            <service name="Server.MyService">
                <endpoint 
                    address="net.tcp://localhost:1234/MyService" 
                    binding="netTcpBinding"
                    contract="Server.IMyService" /> 
            </service> 
        </services> 
    </system.serviceModel>
</configuration>

This is an example of the app.config after adding the compact message encoder:

<?xml version="1.0" encoding="utf-8" ?>
<configuration> 
    <system.serviceModel> 
        <services> 
            <service name="Server.MyService">

            <!-- Set the binding of the endpoint to customBinding -->
            <endpoint 
                    address="net.tcp://localhost:1234/MyService" 
                    binding="customBinding"
                    contract="Server.IMyService" /> 
            </service> 
        </services> 

        <!-- Defines a new customBinding that contains the compactMessageEncoding -->
        <bindings> 
            <customBinding> 
                <binding name="compactBinding"> 
                    <compactMessageEncoding>

                <!-- Defines the inner message encoder as binary encoder -->
                <binaryMessageEncoding /> 
                    </compactMessageEncoding> 
                    <tcpTransport /> 
                </binding> 
            </customBinding> 
        </bindings> 

    <!-- Adds the extension DLL so the WCF can find the compactMessageEncoding -->
        <extensions> 
            <bindingElementExtensions> 
                <add name="compactMessageEncoding" 
		type="Amib.WCF.CompactMessageEncodingElement, 
		CompactMessageEncoder, Version=1.0.0.0, 
		Culture=neutral, PublicKeyToken=null" />
            </bindingElementExtensions> 
        </extensions> 

     </system.serviceModel>
</configuration>

Client config Change

This is an example of app.config before adding the compact message encoder:

<?xml version="1.0" encoding="utf-8" ?>
<configuration> 
    <system.serviceModel> 
        <client> 
            <endpoint
                address="net.tcp://localhost:1234/MyService"
                binding="customBinding"
                bindingConfiguration="compactBinding"
                contract="Client.IMyService" />
        </client> 
    </system.serviceModel>
</configuration>

This is an example of the app.config after adding the compact message encoder:
<?xml version="1.0" encoding="utf-8" ?>
<configuration> 
    <system.serviceModel> 
        <client> 
            <endpoint
                address="net.tcp://localhost:1234/MyService"
                binding="customBinding"
                bindingConfiguration="compactBinding"
                contract="Client.IMyService" />
        </client> 

        <!-- Defines a new customBinding that contains the compactMessageEncoding --> 
        <bindings> 
            <customBinding> 
                <binding name="compactBinding">
                    <compactMessageEncoding> 
                        <binaryMessageEncoding/> 
                    </compactMessageEncoding>
                    <tcpTransport /> 
                </binding> 
            </customBinding> 
        </bindings>
        
    <!-- Adds the extension DLL so the WCF can find the compactMessageEncoding -->
        <extensions> 
            <bindingElementExtensions> 
                <add name="compactMessageEncoding" 
		type="Amib.WCF.CompactMessageEncodingElement, 
		CompactMessageEncoder, Version=1.0.0.0, 
		Culture=neutral, PublicKeyToken=null" /> 
            </bindingElementExtensions> 
        </extensions>

    </system.serviceModel>
</configuration>

Limitations & Workarounds

  1. All messages are compressed on the channel even if it will cause the message to inflate. This happens when the message is small.
  2. The CompactMessageEncoder supports only Buffered transport and not Strearmed transport.
  3. Using the CompactMessageEncoder on client and server that run on the same machine may downgrade performance.
  4. The WCF configuration editor works partially with the CompactMessageEncoder, therefore part of the configuration must be done manually with the XML text editor.
  5. Each time the WCF configuration editor opens the app.config file, it asks about the safety of the CompactMessageEncoder.dll. I don't know how to get rid of this behavior.
  6. The configuration of the binaryMessageEncoding and the textMessageEncoding cannot be edited within the WCF configuration editor. In order to overcome this, remove the compactMessageEncoding element from the app.config (leaving its children), and then open it with the WCF configuration editor. Afterwards, add the compactMessageEncoding element back.

Disclaimer

THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.

History

  • 5th September, 2007: Initial version

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Share

About the Author

Ami Bar
Software Developer (Senior)
Israel Israel
B.Sc. in Computer Science.
Works as Software Developer.

You may also be interested in...

Comments and Discussions

 
QuestionHow to implement compression in Huge data return from WCF service. Pin
Manjunathabe0118-Feb-12 22:25
memberManjunathabe0118-Feb-12 22:25 
QuestionCompress only messages above 50 KB? Pin
sun2117015-Jul-11 7:21
membersun2117015-Jul-11 7:21 
AnswerRe: Compress only messages above 50 KB? Pin
jogibear99887-Sep-13 8:20
memberjogibear99887-Sep-13 8:20 
QuestionIt works great Pin
sun2117014-Jul-11 21:02
membersun2117014-Jul-11 21:02 
Questionapplication/x-gzip is same as gzip? Pin
sun2117014-Jul-11 20:53
membersun2117014-Jul-11 20:53 
GeneralMy vote of 5 Pin
Santiago Santos Cortizo24-Mar-11 3:35
memberSantiago Santos Cortizo24-Mar-11 3:35 
QuestionIs it compatible for ADO.NET Data Services? Pin
Dmytro Kurylovych19-Apr-10 6:49
memberDmytro Kurylovych19-Apr-10 6:49 
AnswerRe: Is it compatible for ADO.NET Data Services? Pin
Ami Bar19-Apr-10 7:34
memberAmi Bar19-Apr-10 7:34 
AnswerRe: Is it compatible for ADO.NET Data Services? Pin
Dmytro Kurylovych19-Apr-10 12:26
memberDmytro Kurylovych19-Apr-10 12:26 
QuestionRe: Is it compatible for ADO.NET Data Services? Pin
Ami Bar19-Apr-10 22:59
memberAmi Bar19-Apr-10 22:59 
AnswerRe: Is it compatible for ADO.NET Data Services? Pin
Dmytro Kurylovych20-Apr-10 2:08
memberDmytro Kurylovych20-Apr-10 2:08 
QuestionHow to use this with webHttpBinding? Pin
Dmytro Kurylovych18-Apr-10 13:05
memberDmytro Kurylovych18-Apr-10 13:05 
AnswerRe: How to use this with webHttpBinding? Pin
Hardy_Smith11-May-10 10:52
memberHardy_Smith11-May-10 10:52 
QuestionCan it work on pure SOAP? Pin
The Geek3-Apr-10 3:07
memberThe Geek3-Apr-10 3:07 
AnswerRe: Can it work on pure SOAP? Pin
Ami Bar3-Apr-10 4:43
memberAmi Bar3-Apr-10 4:43 
QuestionBinding support Pin
pkp0015-Jan-10 1:18
memberpkp0015-Jan-10 1:18 
AnswerRe: Binding support Pin
Hardy_Smith5-Jan-10 4:02
memberHardy_Smith5-Jan-10 4:02 
GeneralThank you. [modified] Pin
Tariq Salah19-May-09 9:45
memberTariq Salah19-May-09 9:45 
GeneralSilverlight client compatibility Pin
bigquick11-Mar-09 13:16
memberbigquick11-Mar-09 13:16 
GeneralRe: Silverlight client compatibility Pin
jogibear99887-Sep-13 22:21
memberjogibear99887-Sep-13 22:21 
GeneralRe: Silverlight client compatibility Pin
jogibear99887-Sep-13 22:23
memberjogibear99887-Sep-13 22:23 
GeneralMessage level encryption Pin
Stonemaster8428-Nov-08 5:02
memberStonemaster8428-Nov-08 5:02 
GeneralRe: Message level encryption Pin
Ami Bar28-Nov-08 11:35
memberAmi Bar28-Nov-08 11:35 
GeneralRe: Message level encryption Pin
tumanov_sergey@inbox.ru8-Oct-09 0:45
membertumanov_sergey@inbox.ru8-Oct-09 0:45 
GeneralRe: Message level encryption Pin
Hardy_Smith11-May-10 10:43
memberHardy_Smith11-May-10 10:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161208.2 | Last Updated 5 Sep 2007
Article Copyright 2007 by Ami Bar
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid