locked
GZip compression with WCF hosted on IIS7 RRS feed

  • Question

  • 3 vote down star
    1

    So I'm going to add my query to the small ocean of questions on the subject.

    I'm trying to enable GZip compression on large soap responses from a WCF service. So far, I've followed instructions here and in a variety of other places to enable dynamic compression on IIS. Here's my dynamicTypes section from the applicationHost.config:

    
    
    <dynamicTypes>
      <add mimeType="text/*" enabled="true" />
      <add mimeType="message/*" enabled="true" />
      <add mimeType="application/x-javascript" enabled="true" />
      <add mimeType="application/atom+xml" enabled="true" />
      <add mimeType="application/xaml+xml" enabled="true" />
      <add mimeType="application/xop+xml" enabled="true" />
      <add mimeType="application/soap+xml" enabled="true" />
      <add mimeType="*/*" enabled="false" />
    </dynamicTypes>

    And also:

    
    
    <urlCompression doDynamicCompression="true" doStaticCompression="true" />

    Though I'm not so clear on why that's needed.

    Threw some extra mime-types in there just in case. I've implemented IClientMessageInspector to add Accept-Encoding: gzip, deflate to my client's HttpRequests. Here's an example of a request-header taken from fiddler:

    
    
    POST http://[omitted]/TestMtomService/TextService.svc HTTP/1.1
    Content-Type: application/soap+xml; charset=utf-8
    Accept-Encoding: gzip, deflate
    Host: [omitted]
    Content-Length: 542
    Expect: 100-continue

    Now, this doesn't work. There's simply no compression happening, no matter what the size of the message (tried up to 1.5Mb). I've looked at this post , but have not run into an exception as he describes, so I haven't tried the CodeProject implementation that he proposes. Also I've seen a lot of other implementations that are supposed to get this to work, but cannot make sense of them (e.g., msdn's GZip encoder ). Why would I need to implement the encoder, or the code-project solution? Shouldn't IIS take care of the compression?

    So what else do I need to do to get this to work?

    Joni

    EDIT: I thought the WCF bindings might be worth posting, though I'm not sure if they're relevant (these are from client):

    
    
    <system.serviceModel>
    <bindings>
      <wsHttpBinding>
      <binding name="WsTextBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
       receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
       transactionFlow="false" hostNameComparisonMode="StrongWildcard"
       maxBufferPoolSize="5000000" maxReceivedMessageSize="5000000"
       messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
       allowCookies="false">
       <readerQuotas maxDepth="32" maxStringContentLength="5000000"
        maxArrayLength="5000000" maxBytesPerRead="5000000" maxNameTableCharCount="5000000" />
       <reliableSession ordered="true" inactivityTimeout="00:10:00"
        enabled="false" />
       <security mode="None">
        <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
        <message clientCredentialType="None" negotiateServiceCredential="false"
         algorithmSuite="Default" establishSecurityContext="false" />
       </security>
    <client>
     <endpoint address="http://[omitted]/TestMtomService/TextService.svc"
      binding="wsHttpBinding" bindingConfiguration="WsTextBinding" behaviorConfiguration="GzipCompressionBehavior"
      contract="TestMtomModel.ICustomerService" name="WsTextEndpoint">
     </endpoint>
    </client>
    <behaviors>
     <endpointBehaviors>
      <behavior name="GzipCompressionBehavior">
       <gzipCompression />
      </behavior>
     </endpointBehaviors>
    </behaviors>
    <extensions>
     <behaviorExtensions>
      <add name="gzipCompression"
         type="TestMtomModel.Behavior.GzipCompressionBehaviorExtensionElement, TestMtomModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
     </behaviorExtensions>
    </extensions>
      </binding>
     </wsHttpBinding>
    </bindings>

    Monday, April 26, 2010 2:59 PM

Answers

  • Hi,

    WCF doesn't impelment Gzip encoding function, so it cannot send gzip encoded request, nor decode the response compressed by server(iis). To enable Gzip compression in wcf, a feasible way is creating custom encoder, encode/decode the stream manually.

    MSDN samples contain a Gzip encoder, to utilize this encoder, we need use custom binding. Here is an sample config file

    <configuration>
        <system.serviceModel>
          <extensions>
            <bindingElementExtensions>
              <add name="gzipMessageEncoding" type="Microsoft.ServiceModel.Samples.GZipMessageEncodingElement, GZipEncoder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
            </bindingElementExtensions>
          </extensions>
            <bindings>
                <customBinding>
                    <binding name="b1">
                      <gzipMessageEncoding innerMessageEncoding="textMessageEncoding" />
                      <httpTransport/>
                    </binding>
                </customBinding>
            </bindings>
            <client>
                <endpoint address="http://myhost/myservice/cu"
                    binding="customBinding" bindingConfiguration="b1"
                    contract="ServiceReference1.IService1" name="CustomBinding_IService1">
                </endpoint>
            </client>
        </system.serviceModel>
    </configuration>

    Thanks,


    Mog Liang
    • Marked as answer by Mog Liang Monday, May 3, 2010 9:43 AM
    Wednesday, April 28, 2010 3:30 AM

All replies

  • Me too tried all these options but all in vain, I tried one last sample from the link http://weblogs.asp.net/cibrax/archive/2006/03/29/WS_2D00_Compression-for-WCF.aspx , which helpe me a lot, only thing this code will give errors while compile it seems this code has bee created in WCF beta, so some of the classed are renamed you need to make app to compile, It will just create one end-point behavior for compression with diff options like GZip, deflat and etc. you need to configure in the servic and client

    Monday, April 26, 2010 5:44 PM
  • Hi,

    WCF doesn't impelment Gzip encoding function, so it cannot send gzip encoded request, nor decode the response compressed by server(iis). To enable Gzip compression in wcf, a feasible way is creating custom encoder, encode/decode the stream manually.

    MSDN samples contain a Gzip encoder, to utilize this encoder, we need use custom binding. Here is an sample config file

    <configuration>
        <system.serviceModel>
          <extensions>
            <bindingElementExtensions>
              <add name="gzipMessageEncoding" type="Microsoft.ServiceModel.Samples.GZipMessageEncodingElement, GZipEncoder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
            </bindingElementExtensions>
          </extensions>
            <bindings>
                <customBinding>
                    <binding name="b1">
                      <gzipMessageEncoding innerMessageEncoding="textMessageEncoding" />
                      <httpTransport/>
                    </binding>
                </customBinding>
            </bindings>
            <client>
                <endpoint address="http://myhost/myservice/cu"
                    binding="customBinding" bindingConfiguration="b1"
                    contract="ServiceReference1.IService1" name="CustomBinding_IService1">
                </endpoint>
            </client>
        </system.serviceModel>
    </configuration>

    Thanks,


    Mog Liang
    • Marked as answer by Mog Liang Monday, May 3, 2010 9:43 AM
    Wednesday, April 28, 2010 3:30 AM
  • As Mog Liang said you could use the GZip encoder from msdn sample,  Since it can be achieved throught custom binding, you need inject/add the behaviors for each an every requirement , for example if want support WS-*, you need to manuall add those to custom binding, thats the only reason i went for endpoint behavior type, here i created the compression utility with different options (GZip, Deflat and mode like Fast, medium, Normal) as a endpoint behaviour and plugged in any binding we need.

    The only disadvantage i could see from my approach is it just compress the Soap Body alone not the entire message.

    Wednesday, April 28, 2010 5:04 PM
  • From the documents it sounds like in .NET 4.0 that a client will handle response messages that have been gzip compressed through the standard mechanisms in IIS.
    Wednesday, June 30, 2010 2:11 PM
  • Just a note that WCF can provide selectively compressed responses by using return type stream and using the gzip stream compression provided within .NET 4.0.  We have used this to selectively compress large contracts for instance.  Also useful to return static data that is stored in DB as compressed so that it need not be re-compressed for each request.  E.g.

    [WebGet(BodyStyle = WebMessageBodyStyle.Bare)]

    Stream MethodName() {

    // Return data stored as gzip depending on header, else decompress and send

    }

    Tuesday, December 4, 2012 10:55 PM