如何使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)我不想压缩/解压缩仅仅是soap正文,而是整个消息。
有任何想法/解决方案吗?
*已解决*
似乎发生的是WCF最终会要求系统网络中某个深层工厂提供HttpWebRequest实例,而我们提供了将被要求创建所需实例的帮助程序。
在WCF客户端配置文件中,只需要一个简单的basicHttpBinding,无需任何自定义扩展。
当应用程序运行时,客户端Http请求包含头部"Accept-Encoding: gzip, deflate",服务器返回经过gzip压缩的Web响应,客户端在交给WCF之前透明地解压缩http响应。
当我尝试将这种技术应用于Web服务时,发现它不起作用。虽然辅助类的执行方式与WCF客户端使用时相同,但http请求不包含"Accept-Encoding: ..."头。
为了使这对Web服务起作用,我不得不编辑Web代理类并添加此方法:
请注意,无论应用程序配置文件中是否存在CompressibleHttpRequestCreator和块,都没有关系。对于Web服务,只有在Web服务代理中覆盖GetWebRequest才有效。
在IIS上,我按照这里的说明来使IIS 6 gzip所有由.svc wcf服务发出的响应(其中请求包含“Accept-Encoding:gzip,deflate”)。
在客户端上,我按照这里和这里的说明来将此标头注入到Web请求中:“Accept-Encoding:gzip,deflate”。
Fiddler2显示响应是二进制的而不是旧的Xml。
客户端崩溃并引发异常,基本上说没有Xml标题,这当然是正确的。
在我的IClientMessageInspector中,在调用AfterReceiveReply之前应用程序崩溃。
一些进一步的说明:
(1)我不能更改WCF服务或客户端,因为它们由第三方提供。但是,如果这是正确的方向,我可以通过配置附加行为和/或消息检查器。
(2)我不想压缩/解压缩仅仅是soap正文,而是整个消息。
有任何想法/解决方案吗?
*已解决*
无法编写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最终会要求系统网络中某个深层工厂提供HttpWebRequest实例,而我们提供了将被要求创建所需实例的帮助程序。
在WCF客户端配置文件中,只需要一个简单的basicHttpBinding,无需任何自定义扩展。
当应用程序运行时,客户端Http请求包含头部"Accept-Encoding: gzip, deflate",服务器返回经过gzip压缩的Web响应,客户端在交给WCF之前透明地解压缩http响应。
当我尝试将这种技术应用于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才有效。