Scott Hanselman

Enabling dynamic compression (gzip, deflate) for WCF Data Feeds, OData and other custom services in IIS7

March 30, '11 Comments [10] Posted in ASP.NET | IIS | OData
Sponsored By

I'm working on a thing that uses an HttpWebRequest to talk to a backend WCF Data Service and it'd be ideal if the traffic was using HTTP Compression (gzip, deflate, etc).

On the client side, it's easy to just add code like this

request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate

or more manually

var request = HttpWebRequest.Create("http://foofoo");
request.Headers["Accept"] = "application/json";
request.Headers["Accept-Encoding"] = "gzip, deflate";

However, you need to make sure this is installed and turned on in IIS7 in you server.

Launch your IIS Manager and go to the Compression module.

Compression Button in IIS Manager

There's check boxes, but it's not installed you may see this yellow alert on the right side.

Compression Alert in IIS Manager

If it's not installed, go to the Server Manager, Roles, Web Server. Under Role Services, check your installed Roles. If Dynamic Compression isn't installed, click Add Roles and install it.

The Dynamic Compression module in IIS manager is installed

You can go back to compression for your site and ensure Dynamic Compression is checked. At this point, Dynamic Compression should be setup, but you really need to be specific about what mimeTypes will be compressed.

Back in IIS Manager, go to the page for the SERVER, not the SITE. Click on Configuration Editor:

The Configuration Editor in IIS Manager

From the dropdown, select system.webServer/httpCompression:

Selecting the httpCompression node in the Configuration Editor in IIS Manager

Then click on Dynamic Types and now that you're in the list editor, think about what types you want compressed. By default */* is False, but you could just turn that on. I chose to be a little more picky and added application/atom+xml, application/json, and application/atom+xml;charset=utf-8 as seen below. It's a little gotcha that application/atom+xml and application/atom+xml;charset=utf-8 are separate entries. Feel free to add what ever mimeTypes you like in here.

Adding MimeTypes graphically in IIS Manager

After you've added them and closed the dialog, be sure to click Apply and Restart your IIS Service to load the new module.

GUIs suck! Command Lines Rule!

If you find all this clicking and screenshots offensive, then do it all from the command line using AppCmd for IIS7. That's lovely also.

appcmd.exe set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/json',enabled='True']" /commit:apphost
appcmd.exe set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/atom%u002bxml',enabled='True']" /commit:apphost
appcmd.exe set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/atom%u002bxml;charset=utf-8',enabled='True']" /commit:apphost

Do check your ApplicationHost.config after running this command. See how we had to escape the "+" in "atom+xml" above and made it "atom%u002bxml"? Make sure that + got into your applicationHost.config unescaped. It should look like this in the System.webServer/httpCompression section.





Now, use Fiddler to confirm that compression is turned on by sending a request with the header "Accept-Encoding: gzip, deflate" included. Make sure that Fiddler's "AutoDecode" and Transforms are turned off if you really want to be sure you're looking at the raw stuff.

Confirming in Fiddler that gzip compression is turned on

Turning on Compression is a VERY low effort and VERY high reward thing to do on your servers, presuming they aren't already totally CPU-bound. If you're doing anything with phones or services over low-bandwidth 3G or EDGE networks, it's a total no brainer. Make sure you know what's compressed on your systems and what's not, and if not, why not.

Be explicit and know what your system/sites HTTP Headers are doing. Compression is step 0 in service optimization. I think I mentioned this in 2004. :)

Enjoy!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. I am a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Wednesday, March 30, 2011 2:54:52 AM UTC
Out of curiosity, did you actually compare the response timings before and after compression? I have found that despite the fact that the payload is significantly reduced the transmission time is often worse or only marginally better. The significant factor seems to be related to the infrastructure that sits between you and the server. If it's on your own lan then you will likely see a good benefit. If you are going across a DSL to an ISP, or across a VPN then there is possibly hardware compression going on that will negate the performance benefits of compression.

The other factor to consider is that if you enable compression, then chunked encoding is automatically turned on, which adds a small amount of additional overhead. For me, I found 100K payloads seems to be the optimal size for enabling compression, but that was not based on any rigorous benchmarking.

Of course you still get the benefits of reduced bandwidth consumption, but sometimes pure speed is the objective. :-)
Wednesday, March 30, 2011 3:28:08 AM UTC
Can this be enabled in IIS Express? I've tried adding <add mimeType="application/atom+xml;charset=utf-8" enabled="true" />to applicationhost.config even though application/atom+xml is there already, but no dice.
Wednesday, March 30, 2011 5:15:19 AM UTC
Best is to enable javascript compression too, but one has to change the mime-type as described here: http://coderjournal.com/2008/04/iis-7-compress-javascript-gzip/
Wednesday, March 30, 2011 7:37:58 AM UTC
Just curious, instead of
application/atom+xml;charset=utf-8
and
application/atom+xml

Couldn't you just use
application/atom+xml*

(alternatively application/atom+xm* if the wildcard doesn't match "nothing")
Wednesday, March 30, 2011 9:09:24 PM UTC
Yes, it should work in IIS Express. Make sure the appcmd.exe added the + in the atom+xml stuff. If you use just a + then it'll turn into a space because it looks like it's escaped.

Seoren - Not sure, good idea! I'll try that. Did you?

Stefan - Great point. I wonder if someone could make a NuGet package that enabled compression?
Sunday, April 10, 2011 3:59:27 PM UTC
Scott, I think it would be really helpful for the world, if you/MS could provide a full code sample to do this for WCF services hosted in CODE (not IIS) as well.

I've managed to do this for my own WCF services and anjoy deflate compression in my hosted wcf services across our network, but this is generally really hard and not a very documented scenario
Monday, April 11, 2011 8:42:13 PM UTC
I'm just getting started with WCF. I've got a Windows Forms app written in VB that uses WCF to communicate with a service on a remote server. How would I go about implementing compression in something like that? Do I put something in my Service Reference, or some configuration file?

Thanks!
Sunday, April 17, 2011 4:24:07 AM UTC
Hi,

Good article. Can you please advice us what are the other important headers that need to be taken care of? I'm just about to start providing my own services over the web.

Thanks
Monday, April 18, 2011 5:50:32 AM UTC
Hi Scott

Thanks for this write-up. I've seen dramatic improvements in actual response times (compression + transfer time as a whole). I did not realise that the Mime types had to be configures specifically since */* is disabled by default.

I'll chime in about the Self Hosted WCF compression (or the of it). The argument made sense to include the feature in IIS and not as part of the WCF binding, but from an optimization point of view it should be available as standard in the WCF stack.

Thanks

Pieter
Snympi
Saturday, July 30, 2011 7:18:24 PM UTC
With my ODATA ATOM feed to my WCF app, without compression, the server returns ~1MB files for a data set with 200 rows. ODATA ATOM files are very verbose -- Gzip can compress one by a factor of 50. However, because of chunking, the actual compression factor is about 10. I see a factor of 5 to 10 improvement in response time for refreshing the data.
howiezowie
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.