WCF, basicHTTPBinding and compression

I am working on a distributes WPF application.  This application has rich client UI, while getting the data from a database server.  One complication is that this software will be installed at a several companies across the US.  All the installation have to communicate with central application server that will be hosted inside a data center.  As I was working on  a class that provides a list of customers (only about 3,500 rows), I decided to measure the traffic and performance.  I was rather unpleasantly surprised with the message size.  It was 7.5MB in Fiddler 2.  By the way, if you want to measure local traffic in Fiddler while using basicHTTPBinding with WCF, set your endpoint to 127.0.0.1. (yes, you need that trailing period) in order to trick Fiddler into thinking that this is external communication.  When I tried to switch to custom binding using binary messaging, the size only shrunk by 1 MB!  I was expecting much more than that…  Here is how I accomplished that:

<customBinding>
                <binding name="NetHttpBinding" receiveTimeout="00:10:00"
                        sendTimeout="00:10:00"
                        openTimeout="00:10:00">
                    <reliableSession />
                    <binaryMessageEncoding  maxReadPoolSize="2147483647" maxWritePoolSize="2147483647" maxSessionSize="2147483647">
                        <readerQuotas
                            maxBytesPerRead="2147483647"
                            maxArrayLength="2147483647"
                            maxStringContentLength="2147483647"
                            maxDepth="1024"/>
                    </binaryMessageEncoding>
                    <httpTransport maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" />
                </binding>
            </customBinding>

So, what next?

I thought of compression next.  Guess what, WCF does not have a built in compression mechanisms.

So, I found a few posts of similar implementation (all years old) and fix bugs and extended them to do what I need.  I got the message size down to 400 KB (or so), which is more that I would like, but 90% compression is not something I am going to complain about.  I did not want to switch binding because of firewall issues.

Here is the mechanism that was used.  We extended the WCF behavior by defining a class that implements BehaviorExtensionElement.  Once you do that, you can reference it inside your configuration file as so:

<extensions>
            <behaviorExtensions>
                <add name="compression" type="Compression.CompressionBehaviorSection, Compression, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b99ba6caceb1e8ad"/>
            </behaviorExtensions>
        </extensions>

And

<behaviors>
            <serviceBehaviors>
                <behavior name="WcfPortalBehavior">
                    <serviceMetadata httpGetEnabled="true"/>
                    <serviceDebug includeExceptionDetailInFaults="true"/>
                    <compression/>
                </behavior>
            </serviceBehaviors>
        </behaviors>The key class in implementation has to implement the following interfaces: IEndpointBehavior (client side)

and IServiceBehavior (server side).  I actually combined both in the same class.  You would also need to implement message inspector interfaces that WCF will call if they are registered to perform actions on the message.  These interfaces are: IDispatchMessageInspector (server side) and IClientMessageInspector(client side)

2 Comments

Leave a Reply to Pete Cancel reply

Your email address will not be published. Required fields are marked *