如何使用 IIS 7.5 压缩来自 ASP.NET MVC 的 Json 结果

Posted

技术标签:

【中文标题】如何使用 IIS 7.5 压缩来自 ASP.NET MVC 的 Json 结果【英文标题】:How do I compress a Json result from ASP.NET MVC with IIS 7.5 【发布时间】:2011-01-09 10:37:27 【问题描述】:

我无法让 IIS 7 正确压缩来自 ASP.NET MVC 的 Json 结果。我在 IIS 中启用了静态和动态压缩。我可以用 Fiddler 验证普通的 text/html 和类似的记录是否被压缩。查看请求,存在接受编码 gzip 标头。响应的 mimetype 为“application/json”,但未压缩。

我发现问题似乎与 MimeType 有关。当我包含mimeType="*/*" 时,我可以看到响应已正确压缩。如何在不使用通配符 mimeType 的情况下让 IIS 进行压缩?我认为这个问题与 ASP.NET MVC 生成内容类型标头的方式有关。

CPU 使用率远低于动态限制阈值。当我检查来自 IIS 的跟踪日志时,我可以看到它由于找不到匹配的 mime 类型而无法压缩。

<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>

【问题讨论】:

我无法使用通配符 mimetype,因为我在 IE8 中遇到了一个奇怪的问题 - 当请求被 IIS 进一步压缩时,它似乎很难下载 .zip 文件。 Firefox 3.5 不受影响。 【参考方案1】:

确保您的 %WinDir%\System32\inetsrv\config\applicationHost.config 包含这些:

<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>

来自@AtanasKorchev 的link。

正如@simon_weaver 在 cmets 中所说,您可能在 64 位 Windows 上使用 32 位编辑器编辑了错误的文件,请使用 notepad.exe 确保确实修改了此文件。

【讨论】:

NTOE:如果我觉得applicationHost.config 不见了,您可能是在使用 32 位编辑器的 64 位机器上。当然,在备份后尝试记事本。 west-wind.com/weblog/posts/2008/Aug/09/… 几个小时,我告诉你,我已经花了几个小时试图找出为什么我的 gzip 压缩应用程序/json 没有从我的 IIS 中出来......这终于奏效了!谢谢! 不要忘记对应用程序池进行回收【参考方案2】:

我已成功使用突出显示的方法here。

【讨论】:

我以前看过那篇文章,但认为它没有添加任何新的或有用的东西。好吧,似乎与其他 mime 类型不同,您需要为 IIS 7 指定内容编码来压缩来自 ASP.NET MVC 的应用程序/json 响应。说application/json 是不够的;它必须是application/json; charset=utf-8 NTOE:如果applicationHost.config 在我看来我想念你可能是在使用 32 位编辑器的 64 位机器上。当然,在备份后尝试记事本。 west-wind.com/weblog/posts/2008/Aug/09/…【参考方案3】:

Use this guide

这些答案都不适合我。我确实注意到了 application/json; charset=utf-8 不过是 mime 类型。

【讨论】:

+1:这对我有用,使用 application/json; charset=utf-8 mime-type :o) 这对我有用,而且您需要记住重新启动服务器而不仅仅是网站。即在启动inetmgr 后点击您的服务器名称并直接前往Manage Server 部分 - 使用该重新启动而不是单个网站重新启动【参考方案4】:

我推荐this approach 创建CompressAttribute类,并设置目标动作。

【讨论】:

只有在其他一切都失败时? IIS7+ 不应该做得更好吗? 这是一个不错的解决方案,因为您可以缓存和压缩,而 IIS 只会缓存或压缩 这也是一个很好的方法,因为压缩小消息在压缩/解压缩中的成本可能比在原始数据传输中的成本更高。为应用程序中的所有 JSON 下载设置 gzip 实际上会花费时间来处理这些较小的消息,因此仅装饰大型 (r) 下载有其优势。 更新了 archive.org 的链接【参考方案5】:

针对 ASP.NET 4.x 更新的 ActionFilterAttribute 方法并包括 Brotli.NET 包。

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);
        
    

【讨论】:

以上是关于如何使用 IIS 7.5 压缩来自 ASP.NET MVC 的 Json 结果的主要内容,如果未能解决你的问题,请参考以下文章

IIS 7.5、ASP.NET、模拟和访问 C:\Windows\Temp

IIS 7.5 ASP.Net 和远程共享

ASP.Net / IIS 7.5 无法识别用于 OutputCache 的 jMeter

IIS 7.5 上的 ASP.NET MVC

IIS 7.5 上的 ASP.NET MVC

Win7 下IIS(7.5)发布 ASP.NET MVC