Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GZip compression with WCF hosted on IIS7

Tags:

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.

like image 732
joniba Avatar asked Apr 26 '10 11:04

joniba


2 Answers

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.

like image 71
Marko Avatar answered Dec 14 '22 22:12

Marko


This is basically the same answer as @marko - with detailed steps. 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.

like image 23
Simon_Weaver Avatar answered Dec 14 '22 20:12

Simon_Weaver