Web API Gzip未被应用

20

我已经根据这个S/O答案添加了web.config条目来启用gzip压缩Enable IIS7 gzip

然后,在加载ASPX页面时,我检查了Chrome开发人员窗口,并看到响应中的标头:

Cache-Control:private
Content-Encoding:gzip
Content-Length:3669
Content-Type:text/html; charset=utf-8
Date:Wed, 04 Mar 2015 00:46:05 GMT
Server:Microsoft-IIS/7.5
Vary:Accept-Encoding
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET

那就意味着它“运行”了,对吗?但是在进行 Web API 调用时寻找该标题时,它并不存在:

Cache-Control:no-cache
Content-Length:551
Content-Type:application/json; charset=utf-8
Date:Wed, 04 Mar 2015 00:53:05 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/7.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET

我尝试了各种不同的配置(从上面链接的S/O回答中推荐的那个开始)。最后,在绝望的情况下,我将它设置为这样,我认为它会尝试压缩所有请求(除 */* 外的所有内容都被注释掉):

  <httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
    <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"/>
    <dynamicTypes>
      <add mimeType="*/*" enabled="true"/>
      <!--<add mimeType="text/*" enabled="true"/>
      <add mimeType="message/*" enabled="true"/>
      <add mimeType="application/javascript" enabled="true"/>
      <add mimeType="application/json" enabled="true"/>-->
      <!--<add mimeType="*/*" enabled="false"/> -->
    </dynamicTypes>
    <staticTypes>
      <add mimeType="*/*" enabled="true"/>
      <!--<add mimeType="text/*" enabled="true"/>
      <add mimeType="message/*" enabled="true"/>
      <add mimeType="application/javascript" enabled="true"/>
      <add mimeType="application/json" enabled="true"/>-->
      <!-- add mimeType="*/*" enabled="false"/>-->
    </staticTypes>
  </httpCompression>
  <urlCompression doStaticCompression="true" doDynamicCompression="true"/>

我的Web API方法为什么无法应用GZIP压缩?

更新

我已经尝试了NuGet Web API Compression package以及在IIS Express 8.0(Visual Studio)和本地安装的IIS 7.5中编辑applicationHost.config。但所有这些都产生了相同的结果:对于类似text/*的其他mime类型的请求可以正常工作,但application/json则无法进行gzip压缩。


你是否在构建应用程序时将web.config设置为始终复制到输出目录? - John Odom
是的,新条目绝对存在。 - FirstDivision
8个回答

11

没有防火墙。我已经尝试了在本地IIS Express 8(即Visual Studio)和本地的IIS 7.5,以及同一网络上的服务器上的IIS 7.5上的所有方法。 - FirstDivision
2
好的,事实证明我错了。在同一台开发机上,有一个完整的IIS安装,正在运行应用程序请求路由,它充当反向代理,允许来自本地环境外部的计算机访问_IIS_,然后将请求转发到本地IIS Express实例(不允许外部连接)。即使我在尝试启用gzip时大部分测试都针对本地实例进行,但完整IIS的路由条目在web.config中(相同目录)。删除该web.config条目使NuGet gzip生效。 - FirstDivision
4
谢谢-对我来说,是ESET杀毒软件在内部解压所有响应。解决方法是禁用“网页浏览器”模块。 - NickG

6

感谢上面两种解决方案和其他地方的解决方案,我想提供一步一步的说明,如何使Web API 2.2与http压缩功能正常工作,因为自上述帖子以来,一些包/命名空间已更改,这可能是有益的。

1)使用NuGet程序包管理器控制台安装以下内容;

Install-Package Microsoft.AspNet.WebApi.MessageHandlers.Compression

2) 在WebApiConfig.cs文件中添加以下using语句:

using System.Net.Http.Extensions.Compression.Core.Compressors;
using Microsoft.AspNet.WebApi.Extensions.Compression.Server;

3) 在 WebApiConfig.cs 文件中,将以下代码添加到 Register(HttpConfiguration config) 方法的底部:

GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new ServerCompressionHandler(new GZipCompressor(), new DeflateCompressor()));

4) 编辑您的web.config文件,在system.webServer中添加以下内容;

<urlCompression doStaticCompression="true" doDynamicCompression="true" dynamicCompressionBeforeCache="true" />
<httpCompression>
    <dynamicTypes>
        <clear />
        <add enabled="true" mimeType="text/*" />
        <add enabled="true" mimeType="message/*" />
        <add enabled="true" mimeType="application/x-javascript" />
        <add enabled="true" mimeType="application/javascript" />
        <add enabled="true" mimeType="application/json" />
        <add enabled="false" mimeType="*/*" />
        <add enabled="true" mimeType="application/atom+xml" />
    </dynamicTypes>
    <staticTypes>
        <clear />
        <add enabled="true" mimeType="text/*" />
        <add enabled="true" mimeType="message/*" />
        <add enabled="true" mimeType="application/javascript" />
        <add enabled="true" mimeType="application/atom+xml" />
        <add enabled="true" mimeType="application/xaml+xml" />
        <add enabled="true" mimeType="application/json" />
        <add enabled="false" mimeType="*/*" />
    </staticTypes>
</httpCompression>

这个功能在本地和Azure网站上都能够顺利运行,希望对你也有用!而且无需修改applicationHost.config文件。


5

我已经通过IIS Express 8.0和本地的IIS 7.5尝试了applicationHost.config。但我还没有在我们的开发服务器上尝试过(IIS 7.5)。我已经引入、配置和部署了NuGet包(本地和开发服务器)。所有结果都是相同的。我还没有尝试Fabrik解决方案,但我有一种感觉它几乎与NuGet包相同? - FirstDivision
我没有比较过两者,但我认为区别仅在于实现方式。因此,两者应该产生相同的(压缩)输出。 - Stefan Ossendorf

4

首先。

IIS忽略WEB API响应压缩,因为Web API响应的mime类型不同。

application/json; charset=utf-8

默认的IIS压缩设置不包括此MIME类型,因此它们不会压缩响应。
因此,您需要将此MIME类型添加到<dynamicTypes>部分中。 <add mimeType="application/json; charset=utf-8" enabled="true" /> (或者只是为了测试,就像您做的那样<add mimeType="*/*" enabled="true" />但是 默认情况下,IIS锁定了<httpCompression>部分,以防止外部设置!
因此,您在web.config上指定的任何设置都将被忽略
除非您在applicationHost.config <httpCompression>部分中指定这些设置,或者编辑<httpCompression>部分以允许来自外部的设置。
<section name="httpCompression" allowDefinition="MachineToApplication" overrideModeDefault="Allow" />

1
应该将其设置为被接受的答案,可能其他答案讨论的是旧框架! - Mosta

4

3
我认为你已经在服务器端完成了所有的作业,但问题出在请求上。
为了允许服务器压缩响应, 必须在请求中包含此标头:
Accept-Encoding: gzip, deflate

如果您不这样做,无论在服务器端做什么,响应都永远不会被压缩。

您没有指定您的Web API客户端是哪个,但总有一种方法可以使用客户端API在请求中添加标头。


我的主要测试方式是通过Web API测试客户端,因此它在幕后是一个jquery请求。 Accept-Encoding标头已经存在。不过这个想法不错! - FirstDivision

3

我觉得@Peeticus说的对。

这是我做的让它正常工作的方法:

在运行"Install-Package Microsoft.AspNet.WebApi.MessageHandlers.Compression"或通过GUI添加它之后,您需要更新/App_Start/WebApiConfig.cs

需要使用以下额外的Using语句:

using Microsoft.AspNet.WebApi.MessageHandlers.Compression.Compressors;
using Microsoft.AspNet.WebApi.MessageHandlers.Compression;

在WebApiConfig.Register方法中添加以下内容:

GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new ServerCompressionHandler(new GZipCompressor(), new DeflateCompressor()));

在IISExpress应用程序配置文件中,找到<httpCompression>的<dynamicTypes>元素,并在默认的<add mimeType="/" enabled="false" />之前添加以下内容。
<add mimeType="application/json" enabled="true" />

同样在applicationHost.config中更新<urlCompression />为:
<urlCompression doDynamicCompression="true" />

顺便提一下,我尝试通过更新“ '<section name="httpCompression" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />' ”来允许我在 web.config 中进行这些更改,但这对我没有起作用。此外,我不需要为“application/json; charset=utf-8”添加单独的条目。 - Dane W

1
在您实现NuGet包Microsoft.AspNet.WebApi.MessageHandlers.Compression时,是否已将所需行(如下所示)添加到App_Start\WebApiConfig.cs文件中?请注意,根据该包的主页上的说明,它必须位于该方法中所有其他消息处理程序之后。
GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new ServerCompressionHandler(new GZipCompressor(), new DeflateCompressor()));

这是我在博客中使用的WebApiConfig文件中的示例注册方法:

以下是示例代码:

    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { echo = RouteParameter.Optional }
        );
        GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new ServerCompressionHandler(new GZipCompressor(), new DeflateCompressor()));
    }

这是我提到的博客文章:.Net Web API Compression


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接