Enabling dynamic compression (gzip, deflate) for WCF Data Feeds, OData and other custom services in IIS7
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.
There's check boxes, but it's not installed you may see this yellow alert on the right side.
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.
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:
From the dropdown, select system.webServer/httpCompression:
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.
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.
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. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
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")
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?
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
Thanks!
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
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
Comments are closed.
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. :-)