WCF GZip 压缩请求/响应处理

发布于 2024-08-11 04:02:39 字数 2961 浏览 2 评论 0原文

如何让 WCF 客户端处理已被 IIS GZipped 或 Deflated 的服务器响应?

在 IIS 上,我按照此处的说明进行操作关于如何使 IIS 6 gzip 由 .svc wcf 服务发出的所有响应(其中请求包含“Accept-Encoding:gzip,deflate”)。

在客户端上,我按照此处的说明进行操作此处了解如何将此标头注入到 Web 请求中:“Accept-Encoding: gzip, deflate”。

Fiddler2 显示响应是二进制的,而不是普通的旧 Xml。

客户端崩溃并出现异常,基本上表明没有 Xml 标头,这当然是正确的。

在我的 IClientMessageInspector 中,应用程序在调用 AfterReceiveReply 之前崩溃。

一些进一步的说明:

(1) 我无法更改 WCF 服务或客户端,因为它们是由第三方提供的。但是,如果这是正确的方向,我可以通过配置附加行为和/或消息检查器。

(2) 我不想只压缩/解压缩肥皂体,而是压缩/解压缩整个消息。

有什么想法/解决方案吗?

* 已解决 *

不可能编写 WCF 扩展来实现这些目标。相反,我遵循了这篇CodeProject 文章,该文章提倡使用辅助类:

public class CompressibleHttpRequestCreator : IWebRequestCreate
{
    public CompressibleHttpRequestCreator()
    {
    }

    WebRequest IWebRequestCreate.Create(Uri uri)
    {
        HttpWebRequest httpWebRequest = 
            Activator.CreateInstance(typeof(HttpWebRequest),
            BindingFlags.CreateInstance | BindingFlags.Public | 
            BindingFlags.NonPublic | BindingFlags.Instance,
            null, new object[] { uri, null }, null) as HttpWebRequest;

        if (httpWebRequest == null)
        {
            return null;
        }

        httpWebRequest.AutomaticDecompression =DecompressionMethods.GZip | 
            DecompressionMethods.Deflate;

        return httpWebRequest;
    }
} 

另外,对应用程序配置文件进行了补充:

<configuration>
  <system.net>
    <webRequestModules>
      <remove prefix="http:"/>
      <add prefix="http:" 
            type="Pajocomo.Net.CompressibleHttpRequestCreator, Pajocomo" />
    </webRequestModules>
  </system.net>
</configuration>

似乎正在发生的情况是,WCF 最终要求某些工厂或其他位于 system.net 深处的工厂提供 HttpWebRequest 实例,并且我们提供了帮助程序,该帮助程序将被要求创建所需的实例。

在 WCF 客户端配置文件中,只需要一个简单的 basicHttpBinding,无需任何自定义扩展。

当应用程序运行时,客户端 Http 请求包含标头“Accept-Encoding: gzip, deflate”,服务器返回 gzip 压缩的 Web 响应,客户端在将 http 响应移交给 WCF 之前透明地解压缩该响应。

当我尝试将此技术应用于 Web 服务时,我发现它不起作用。尽管辅助类的执行方式与 WCF 客户端使用时相同,但 http 请求不包含“Accept-Encoding: ...”标头。

为了使此功能适用于 Web 服务,我必须编辑 Web 代理类,并添加此方法:

protected override System.Net.WebRequest GetWebRequest(Uri uri)
{
    System.Net.HttpWebRequest rq = (System.Net.HttpWebRequest)base.GetWebRequest(uri);
    rq.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
    return rq;
}

请注意,应用程序配置文件中的 CompressibleHttpRequestCreator 和块是否存在并不重要。对于 Web 服务,只有重写 Web 服务代理中的 GetWebRequest 才有效。

How do I get a WCF client to process server responses which have been GZipped or Deflated by IIS?

On IIS, I've followed the instructions here on how to make IIS 6 gzip all responses (where the request contained "Accept-Encoding: gzip, deflate") emitted by .svc wcf services.

On the client, I've followed the instructions here and here on how to inject this header into the web request: "Accept-Encoding: gzip, deflate".

Fiddler2 shows the response is binary and not plain old Xml.

The client crashes with an exception which basically says there's no Xml header, which ofcourse is true.

In my IClientMessageInspector, the app crashes before AfterReceiveReply is called.

Some further notes:

(1) I can't change the WCF service or client as they are supplied by a 3rd party. I can however attach behaviors and/or message inspectors via configuration if this is the right direction to take.

(2) I don't want to compress/uncompress just the soap body, but the entire message.

Any ideas/solutions?

* SOLVED *

It was not possible to write a WCF extension to achieve these goals. Instead I followed this CodeProject article which advocate a helper class:

public class CompressibleHttpRequestCreator : IWebRequestCreate
{
    public CompressibleHttpRequestCreator()
    {
    }

    WebRequest IWebRequestCreate.Create(Uri uri)
    {
        HttpWebRequest httpWebRequest = 
            Activator.CreateInstance(typeof(HttpWebRequest),
            BindingFlags.CreateInstance | BindingFlags.Public | 
            BindingFlags.NonPublic | BindingFlags.Instance,
            null, new object[] { uri, null }, null) as HttpWebRequest;

        if (httpWebRequest == null)
        {
            return null;
        }

        httpWebRequest.AutomaticDecompression =DecompressionMethods.GZip | 
            DecompressionMethods.Deflate;

        return httpWebRequest;
    }
} 

and also, an addition to the application configuration file:

<configuration>
  <system.net>
    <webRequestModules>
      <remove prefix="http:"/>
      <add prefix="http:" 
            type="Pajocomo.Net.CompressibleHttpRequestCreator, Pajocomo" />
    </webRequestModules>
  </system.net>
</configuration>

What seems to be happening is that WCF eventually asks some factory or other deep down in system.net to provide an HttpWebRequest instance, and we provide the helper that will be asked to create the required instance.

In the WCF client configuration file, a simple basicHttpBinding is all that is required, without the need for any custom extensions.

When the application runs, the client Http request contains the header "Accept-Encoding: gzip, deflate", the server returns a gzipped web response, and the client transparently decompresses the http response before handing it over to WCF.

When I tried to apply this technique to Web Services I found that it did NOT work. Although the helper class was executed in the same was as when used by the WCF client, the http request did not contain the "Accept-Encoding: ..." header.

To make this work for Web Services, I had to edit the Web Proxy class, and add this method:

protected override System.Net.WebRequest GetWebRequest(Uri uri)
{
    System.Net.HttpWebRequest rq = (System.Net.HttpWebRequest)base.GetWebRequest(uri);
    rq.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
    return rq;
}

Note that it did not matter whether the CompressibleHttpRequestCreator and block from the application config file were present or not. For web services, only overriding GetWebRequest in the Web Service Proxy worked.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

过期以后 2024-08-18 04:02:39

感谢您提供 WCF 提示!我们将在我的商店为服务启用 IIS 压缩,我希望您的解决方案能够发挥作用。
“为了使此功能适用于 Web 服务” - 您是指老式 SoapHttpProtocol 客户端吗?
因为SoapHttpProtocol类有一个内置的EnableDecompression属性,它将自动处理压缩标头和响应处理。

Thanks for your WCF tip! We're going to be enabling IIS compression for services at my shop, and I'm hoping your solution will work.
By "To make this work for Web Services" - did you mean old school SoapHttpProtocol clients?
Because the SoapHttpProtocol class has a built-in EnableDecompression property, which will automatically handle the Compression header and response handling.

千纸鹤带着心事 2024-08-18 04:02:39

这是我对另一个问题的回答主题。这个问题是从 ADO.NET 数据服务的角度提出的,但我的回答纯粹是关于 WCF 的。

Here's an answer I gave to another question on the subject. That questio was asked from the perspective of ADO.NET Data Services, but my answer was purely about WCF.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文