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>
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Gareth Saul
  • 1,307
  • 1
  • 9
  • 19
  • 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. – Gareth Saul Jan 26 '10 at 08:40

5 Answers5

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.

deerchao
  • 10,454
  • 9
  • 55
  • 60
  • 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. http://www.west-wind.com/weblog/posts/2008/Aug/09/Editing-Applicationhostconfig-on-64-bit-Win2008 – Simon_Weaver Mar 05 '13 at 00: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 '16 at 21:07
  • Don't forget to do a Recycle to the Application Pool – Mr_LinDowsMac Feb 01 '17 at 22:35
22

I have successfully used the approach highlighted here.

Atanas Korchev
  • 30,562
  • 8
  • 59
  • 93
  • 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`. – Gareth Saul Jan 26 '10 at 09: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. http://www.west-wind.com/weblog/posts/2008/Aug/09/Editing-Applicationhostconfig-on-64-bit-Win2008 – Simon_Weaver Mar 05 '13 at 00: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.

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
Ryan Kirkman
  • 4,051
  • 2
  • 25
  • 20
  • 1
    +1: this worked for me, using the `application/json; charset=utf-8` mime-type :o) – Andrew Jan 11 '13 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 '14 at 06:28
7

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

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
takepara
  • 10,413
  • 3
  • 34
  • 31
  • 1
    Only when everything else fails? shouldn't IIS7+ do a better job? – Alex Nolasco Jun 17 '10 at 04:31
  • 1
    This is a nice solution because you can cache and compress whereas IIS will only cache or compress – David Hayes May 28 '12 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. – Jason Jackson Sep 04 '13 at 20:25
  • Updated link to archive.org – MatthewMartin Feb 25 '16 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);
        }
    }
}
seagulledge
  • 314
  • 1
  • 2
  • 7