I have a WebAPI controller that returns an HttpResponseMessage
and I want to add gzip compression. This is the server code:
using System.Net.Http;
using System.Web.Http;
using System.Web;
using System.IO.Compression;
[Route("SomeRoute")]
public HttpResponseMessage Post([FromBody] string value)
{
HttpContext context = HttpContext.Current;
context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);
HttpContext.Current.Response.AppendHeader("Content-encoding", "gzip");
HttpContext.Current.Response.Cache.VaryByHeaders["Accept-encoding"] = true;
return new SomeClass().SomeRequest(value);
}
And this is the client code for the ajax call, using jquery:
$.ajax({
url: "/SomeRoute",
type: "POST",
cache: "false",
data: SomeData,
beforeSend: function (jqXHR) { jqXHR.setRequestHeader('Accept-Encoding', 'gzip'); },
success: function(msg) { ... }
When I run this, the server code returns without bugging but the client bugs:
(failed)
net::ERR_CONTENT_DECODING_FAILED
When I look with Fiddler, this is what I see:
What do I need to change to make the web service return gzipped content that the client processes normally? I know I could also do this with an HttpModule or through some setting on IIS but neither option fits the scenario of the hosting:
Please note that I'm not looking for an IIS setting because I don't have access to that (hosting).
One Solution without editing any IIS Setting or Installing any Nuget package is to add a MessageHandler to your WEB API.
This will catch requests with the "AcceptEncoding" Header and compress them using the Build in System.IO.Compression libraries.
And add this handler to your Global.asax.cs
Kudos to Ben Foster. ASP.NET Web API Compression
Just an addendum to enabling compression in IIS via the
applicationHost.config
file.Use the IIS config manager to make the changes or
notepad.exe
to edit the file. I was usingNotepad++
and even though the file was saving, it actually was not.Something to do with 32/64bit environments, configs and the programs that edit them. Ruined my afternoon!!
Add these NuGet packages:
Then and add one line of code to
App_Start\WebApiConfig.cs
:That will do the trick!
Details at:
Hope that helps.
**Updated after comment from @JCisar
Update for ASP.Net Core
Nuget Package is
If you have access to IIS configuration
You cant just apply the header and hope it will be gzipped - the response will not be zipped.
You need remove the header you added and ensure you have the dynamic compression and static content compression are enabled on your IIS server.
One of the commenter's mentioned a good resource link here at stakoverflow that show how to do that:
Enable IIS7 gzip
Note it will only work setting the value in web.config if dynamic compression is already installed (which is not in a default install of IIS)
You can find the information about this on MSDN documentation: http://www.iis.net/configreference/system.webserver/httpcompression
Simple compression
Below is using a simple example of doing your own compression this example is using the Web Api MVC 4 project from visual studio project templates. To get compression working for HttpResponseMessages you have to implement a custom MessageHandler. See below a working example.
See the code implementation below.
Please note that I tried to keep the method doing the same as your example.
Also add the new message handler to the config of your app.
The Custom handler was put together by - Kiran Challa (http://blogs.msdn.com/b/kiranchalla/archive/2012/09/04/handling-compression-accept-encoding-sample.aspx)
There are better examples that implement deflating of inbound streams too you can see examples of that below:
Additionally I found a really nice project that supports all of this on github.
Note while I arrived to this answer by myself Simon in your comments suggested this approach 2 days ago from the date of this answer.