I've been using the compression filter for my MVC actions as detailed here:
http://msdn.microsoft.com/en-us/magazine/gg232768.aspx
I've tried to re-purpose the code to do something similar for Web API, but I've hit a roadblock:
public class CompressAPIAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext filterContext)
{
var preferredEncoding = GetPreferredEncoding(filterContext.Request);
Stream compressedStream = null;
// Compress the response accordingly
var response = filterContext.Response;
response.Headers.Add("Content-encoding", preferredEncoding.ToString());
if (preferredEncoding == CompressionScheme.Gzip)
{
response.Content = new GZipStream(compressedStream, CompressionMode.Compress); //THIS WON'T WORK
}
if (preferredEncoding == CompressionScheme.Deflate)
{
response.Content = new DeflateStream(compressedStream, CompressionMode.Compress); //THIS WON'T WORK
}
return;
}
enum CompressionScheme
{
Gzip = 0,
Deflate = 1,
Identity = 2
}
private CompressionScheme GetPreferredEncoding(HttpRequestMessage request)
{
var acceptableEncoding = request.Headers.AcceptEncoding;
if (acceptableEncoding.Where(h => h.Value.Contains("gzip")).Count() > 0)
return CompressionScheme.Gzip;
if (acceptableEncoding.Where(h => h.Value.Contains("deflate")).Count() > 0)
return CompressionScheme.Deflate;
return CompressionScheme.Identity;
}
Any ideas how I can assign a compressed stream to the response's content?
I should point out this is being hosted in IIS 6.0, which I do not control.
I think you should not do this in an action filter as the modelbinding stage happens before action filters are executed and during modelbinding the formatters could be reading the stream to deserialize it, in which case it would fail.
If you are using IIS, then do the following to setup compression(The following have some snippets from Scott Hanselman's blog post):
Enabled the "Dynamic Compression" feature in IIS.
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:
Now make requests using Accept-Encoding
header and you should see the response as expected.
EDIT ( in addition to above include "application/json; charset=utf-8" to cover both json formats)
If you are using IIS to setup compression, you can modify the file:
C:\Windows\System32\inetsrv\config\applicationHost.config
Add the following tags
<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/atom+xml; charset=utf-8" enabled="true" />
<add mimeType="application/json" enabled="true" />
<add mimeType="application/json; charset=utf-8" enabled="true" />
<!--<add mimeType="application/*" enabled="true" />-->
<add mimeType="*/*" enabled="false" />
<staticTypes>
...
</staticTypes>
</dynamicTypes>
in the section:
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
<!--
add here
-->
<staticTypes>
<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="*/*" enabled="false" />
</staticTypes>
</httpCompression>
After you've added them restart your IIS Service to load the new module.
There is a possibility to increase the level of compression by modifying the tag:
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"
staticCompressionLevel="9" dynamicCompressionLevel="9" />
done :)
PS: remember to enable the dynamic compression under path system.webServer/httpCompression in Configuration Editor for IIS Server
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With