WCF GZip压缩请求/响应处理

时间:2009-11-16 12:02:27

标签: wcf http-headers gzip

如何让WCF客户端处理由IIS进行过GZip或Deflated的服务器响应?

在IIS上,我按照here说明如何使IIS 6 gzip所有响应(请求包含“Accept-Encoding:gzip,deflate”)由.svc wcf services发出。

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

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

客户端崩溃时出现异常,基本上说没有Xml标头,这是真的。

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

进一步说明:

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

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

任何想法/解决方案?

*已解决*

无法编写WCF扩展来实现这些目标。相反,我遵循了提倡帮助类的CodeProject article

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 Proxy类,并添加此方法:

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。

2 个答案:

答案 0 :(得分:2)

感谢您的WCF提示!我们将在我的商店为服务启用IIS压缩,我希望您的解决方案能够正常运行。 通过“使这项工作为Web服务” - 你的意思是老派SoapHttpProtocol客户? 因为SoapHttpProtocol类具有内置的EnableDecompression属性,它将自动处理Compression标头和响应处理。

答案 1 :(得分:1)

Here's an answer I gave关于这个问题的另一个问题。从ADO.NET数据服务的角度提出了这个问题,但我的回答纯粹是关于WCF。