views:

897

answers:

5

Everyone, as far as I'm concerned the question is ansered in EDIT 2. Although it's only a partial solution to the IIS side of the problem, it's what I was looking for.


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>

EDIT 2: Well for anyone else in this mysterious situation, I have a partial solution. I.e., I've gotten IIS7 to at least compress the soap messages from the service (though I now get an exception on the client, but for that there have been several solutions posted). The problem was that the DynamicCompressionModule was not installed on my server. "Installing" it actually, for me, meant simply adding this line to applicationHost.config's section:

<add name="DynamicCompressionModule" image="%windir%\System32\inetsrv\compdyn.dll" />

(Assuming the dll exists in that directory, which in my case it did.) And then adding the module via IIS7's Modules section for the website or server.

A: 

Maybe this can help you: GZip Encoder Sample

Adolfo Abegg
It's a IIS7 configuration issue - he's not asking how to do it with the WCF extensibility model.
larsw
+4  A: 

Try adding 'application/soap+xml; charset=utf-8' as dynamic type in applicationHost. Adding this charset part helped me to enable compression for some JSON responses from my http handler.

Marko
+1 - this is the answer - I had to do exactly this to make compression work WITHOUT using any additional components whatsoever. That is, assuming the dynamic compression module is switched on and installed :)
Andras Zoltan
You might need to enable the same mime type multiple times, as Microsoft tends to do string comparisons rather than content comparisons. (i.e. `application/soap+xml;charset=utf-8`, `application/soap+xml;charset=ISO-8895-1`, `application/soap+xml; charset=ISO-8895-1`)
jrista
A: 

Best bet is to evaluate the specific mime type you are having trouble with (e.g. Fiddler) and ensure that is incorporated in applicationHost.config. If compression is installed and configured correctly, failed request tracing will let you know that compression was not performed with a "NO_MATCHING_CONTENT_TYPE" disposition.

Mike H.
Thanks for the answers guys. However, the IIS side of the problem was already solved. Please read EDIT 2 in the original post. I would have marked the question as the answer if I could, even though it's just a partial solution to the problem, but I can't.
joniba
A: 

with gzip encoder you get client to server compression too - that's why it is worth considering!

addis
A: 

This is basically the same answer as @marko - but with a more detailed guide on how to do it. This is a frustrating topic every time I revisit it so I wanted to outline everything I need to do to get it working.

  • First things first you'll want to be using .NET 4 on IIS7. This is because it wasn't until .NET 4 that WCF was capable of automatically decompressing gzip streams. The details of this are descibed in 'Whats new in WCF 4' (some useful comments in feedback).

    We’ve made that easier when using HTTP by allowing the client to automatically negotiate using gzip or deflate compressed streams and then automatically decompress them.

  • Second, make sure you have enabled the dynamic compression module in IIS. You may need to go to 'Programs and Features' to install it. Be sure that you have it enabled for the web application in question - as it is not a global setting.

  • Now WPF uses the MIME type application/soap+xml; charset=utf-8 for HTTP transmission (at least with wsHttpBinding it does). By default this is NOT classed as a dynamic type so it needs to be added to the applicationHost.config file.

    Just edit this file ON THE SERVER: C:\Windows\System32\Inetsrv\Config\applicationHost.config

    In the <dynamicTypes> node add the following line (BEFORE THE / LINE) :

    <add mimeType="application/soap+xml; charset=utf-8" enabled="true" />
    

    More on the applicationHost.config file

  • Restart IIS

You should now have compressed data - which can be verified in Fiddler.

Simon_Weaver