在客户端上为呼叫WCF服务启用GZIP

时间:2019-01-19 12:02:05

标签: c# wcf compression wcf-binding c#-7.0

我使用很棒的 Scott Hanselman 文章在IIS上启用Dynamic Compression

Enabling dynamic compression (gzip, deflate) for WCF Data Feeds, OData and other custom services in IIS7

在文章开头,他说:

  

在客户端,只需添加这样的代码很容易:

request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate

第一个问题是:我应该在哪里添加以上代码?

我正在使用BasicHttpBinding,现在请考虑以下代码:

using (ServiceReference1.Srv1 client = new ServiceReference1.Srv1Client())
{
    var data = client.GetData(string longText, byte[] file);
}

通过该代码,我从客户端应用程序调用我的服务。现在的问题是,如何使用GZIP自动压缩客户端请求(每个参数),从而导致调用Web服务变得更快?

谢谢

3 个答案:

答案 0 :(得分:1)

request.AutomaticDecompression属性位于HttpWebRequest对象上。 我不确定您是否使用WCF OData服务。根据Scott Hanselman的博客,这应该适用于WCF OData Service。

我猜BasciHttpBinding默认不支持压缩。这个想法来自this blog.

我将创建BehaviorExtensionElement,CompressionBehaviorSection,如下所示。

public class MessageCompressionBehavior : IDispatchMessageInspector, IServiceBehavior, IClientMessageInspector
{

}


public class CompressionBehaviorExtensionElement :BehaviorExtensionElement
{

}

 <extensions> 
            <behaviorExtensions> 
                <add name="compression" type="yournamespace.CompressionBehaviorExtensionElement, yourassembly, Version=...., Culture=neutral, PublicKeyToken=......"/> 
            </behaviorExtensions> 
 </extensions>


<behaviors>
   <serviceBehavior>
         <compression />
   </serviceBehavior>
</behaviors>

然后在基本Http绑定上应用此行为。

IDispatchMessageInspector和IClientMessageInspector将根据是发送还是接收数据来压缩/解压缩数据。

更新日期:2019年1月29日 我昨天发现了另一种方法:

步骤1:如果您的服务是IIS Hosted,则可以启用动态压缩模块。

然后在applicationHost.config中为SOAP消息添加mime类型,如下所示:

<add mimeType="application/soap+xml" enabled="true" />
<add mimeType="application/soap+xml; charset=utf-8" enabled="true" />
<add mimeType="application/soap+xml; charset=ISO-8895-1" enabled="true" />

第2步:自定义IWebRequestCreate

完成此操作后,您将必须使WCF通过HTTP请求发送“ Accept Encoding”标头。您可以如下所示创建自定义IWebRequestCreate

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

第3步:更改客户端配置中的配置 然后,您可以在客户端的app.config或web.config中添加以下设置:

<system.net>
  <webRequestModules>
    <remove prefix="http:"/>
    <add prefix="http:" type="WcfHttpCompressionEnabler.CompressibleHttpRequestCreator, WcfHttpCompressionEnabler, 
        Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  </webRequestModules>
</system.net>

该解决方案的说明at this blog。它还具有示例代码at this link.

我希望这会为您的问题提供足够的帮助。

答案 1 :(得分:1)

这只是我的建议。

您可以定义自己的ClientMessageFormatter,DispatchMessageFormatter。

ClientMessageFormatter用于序列化请求和反序列化响应。

DispatchMessageFormatter用于反序列化请求和序列化请求。

如果您可以使用自己的CompressionAlgorithm通过Gzip或deflate序列化和反序列化请求和响应,则消息将变小。

这两个界面都有下面的方法。

   public void DeserializeRequest(Message message, object[] parameters)
{

}

public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
       }

public object DeserializeReply(Message message, object[] parameters)
{
       }
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
  }

要使用自己的ClientMessageFormatter和DispatchMessageFormatter,应使用EndpointBehavior。

在ApplyClientBehavior和ApplyDispatchBehavior中,应将ClientMessageFormatter设置为ClientOperation的Formatter属性,并将DispatchMessageFormatter设置为DispatchOperation的formatter属性。

此外,要启用动态compressionAlgorithm,最好将您的compressionAlgorithm传递给端点行为,然后该行为将compressionAlgorithm传递给ClientMessageFormatter和DispatchMessageFormatter,以便它可以知道要使用哪种压缩。

仍有许多事情要做,例如,如何使用wcf的默认ClientMessageFormatter和DispatchMessageFormatter结合您自己的ClientMessageFormatter和DispatchMessageFormatter对消息进行序列化和反序列化。

由于wcf的默认格式化程序用于序列化和反序列化请求和响应,因此您可以使用格式化程序在wcf序列化的基础上压缩消息。因此,在使用格式化程序之前,应在endpointbehavior的ApplyDispatchBehavior和ApplyClientBehavior中获得wcf的默认格式化程序。

然后将自己的格式化程序的some属性设置为wcf的默认属性,以便您可以使用wcf的默认格式化程序。

答案 2 :(得分:0)

请求压缩不是服务器或客户端理解的HTTP标准。为此,您必须自己在客户端和服务器上进行操作。

我已经有一段时间没有进行WCF开发了,但是我很确定WCF可以做到这一点。