57

I'm having difficulty making IIS 7 correctly compress a Json result from ASP.NET MVC. I've enabled static and dynamic compression in IIS. I can verify with Fiddler that normal text/html and similar records are compressed. Viewing the request, the accept-encoding gzip header is present. The response has the mimetype "application/json", but is not compressed.

I've identified that the issue appears to relate to the MimeType. When I include mimeType="*/*", I can see that the response is correctly gzipped. How can I get IIS to compress WITHOUT using a wildcard mimeType? I assume that this issue has something to do with the way that ASP.NET MVC generates content type headers.

The CPU usage is well below the dynamic throttling threshold. When I examine the trace logs from IIS, I can see that it fails to compress due to not finding a matching mime type.

<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files" noCompressionForProxies="false">
    <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
    <dynamicTypes>
        <add mimeType="text/*" enabled="true" />
        <add mimeType="message/*" enabled="true" />
        <add mimeType="application/x-javascript" enabled="true" />
        <add mimeType="application/json" enabled="true" />
    </dynamicTypes>
    <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="application/json" enabled="true" />
    </staticTypes>
</httpCompression>
1
  • 1
    I cannot use a wildcard mimetype since I'm encountering a strange issue with IE8 - it appears to have difficulty downloading a .zip file when the request is further gzipped by IIS. Firefox 3.5 is unaffected. Jan 26, 2010 at 8:40

5 Answers 5

62

Make sure your %WinDir%\System32\inetsrv\config\applicationHost.config contains these:

<system.webServer>
    <urlCompression doDynamicCompression="true" />
    <httpCompression>
      <dynamicTypes>
        <add mimeType="application/json" enabled="true" />
        <add mimeType="application/json; charset=utf-8" enabled="true" />       
      </dynamicTypes>
    </httpCompression>
</system.webServer>

From the link of @AtanasKorchev.

As @simon_weaver said in the comments, you might be editing the wrong file with a 32 bit editor on a 64 bit Windows, use notepad.exe to make sure this file is indeed modified.

3
  • 2
    NTOE: if applicationHost.config appears to me missing you're probably on a 64 bit machine using a 32 bit editor. Try notepad AFTER MAKING BACKUP of course. west-wind.com/weblog/posts/2008/Aug/09/… Mar 5, 2013 at 0:32
  • Hours, hours I tell you, I've spent HOURS trying to discover why my gzipped application/json was not coming out of my IIS... This finally worked! Thanks!
    – Aviad P.
    Jan 17, 2016 at 21:07
  • Don't forget to do a Recycle to the Application Pool Feb 1, 2017 at 22:35
22

I have successfully used the approach highlighted here.

2
  • 10
    I'd seen that article before, but dismissed it as not adding anything new or useful. Well, it appears that unlike other mime types, you need to specify the content encoding for IIS 7 to compress application/json responses from ASP.NET MVC. Saying application/json isn't enough; it needs to be application/json; charset=utf-8. Jan 26, 2010 at 9:01
  • NTOE: if applicationHost.config appears to me missing you're probably on a 64 bit machine using a 32 bit editor. Try notepad AFTER MAKING BACKUP of course. west-wind.com/weblog/posts/2008/Aug/09/… Mar 5, 2013 at 0:32
14

Use this guide

None of these answers worked for me. I did take note of the application/json; charset=utf-8 mime-type though.

2
  • 1
    +1: this worked for me, using the application/json; charset=utf-8 mime-type :o)
    – Andrew
    Jan 11, 2013 at 10:37
  • this works for me plus you need to remember to restart the SERVER not just the website. ie after starting inetmgr click on your server name and head right to the Manage Server section - use that restart and not the individual website restart
    – wal
    Jun 25, 2014 at 6:28
7

I recommend this approach
Create CompressAttribute class, and set target action.

4
  • 1
    Only when everything else fails? shouldn't IIS7+ do a better job? Jun 17, 2010 at 4:31
  • 1
    This is a nice solution because you can cache and compress whereas IIS will only cache or compress May 28, 2012 at 23:28
  • 1
    This is also a nice approach in that compressing small messages can cost more in compress/decompress that they would have in vanilla transmission of the data. Setting gzip for all JSON downloads in an application can actually cost time for these smaller messages, so decorating only large(r) downloads has its advantages. Sep 4, 2013 at 20:25
  • Updated link to archive.org Feb 25, 2016 at 21:02
2

The ActionFilterAttribute approach updated for ASP.NET 4.x and Includes Brotli.NET package.

using System;
using System.IO.Compression;
using Brotli;
using System.Web;
using System.Web.Mvc;


public class CompressFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        HttpRequestBase request = filterContext.HttpContext.Request;

        string acceptEncoding = request.Headers["Accept-Encoding"];
        if (string.IsNullOrEmpty(acceptEncoding)) return;

        acceptEncoding = acceptEncoding.ToUpperInvariant();
        HttpResponseBase response = filterContext.HttpContext.Response;

        if (acceptEncoding.Contains("BR"))
        {
            response.AppendHeader("Content-encoding", "br");
            response.Filter = new BrotliStream(response.Filter, CompressionMode.Compress);
        }
        else if (acceptEncoding.Contains("GZIP"))
        {
            response.AppendHeader("Content-encoding", "gzip");
            response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
        }
        else if (acceptEncoding.Contains("DEFLATE"))
        {
            response.AppendHeader("Content-encoding", "deflate");
            response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.