【问题标题】:Enabling GZIP for call WCF service on client在客户端上启用 GZIP 以调用 WCF 服务
【发布时间】:2019-01-19 12:02:04
【问题描述】:

我使用伟大的 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 压缩客户端请求(每个参数),从而导致调用网络服务变得更快?

谢谢

【问题讨论】:

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


【解决方案1】:

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

我猜默认情况下 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 托管的,您可以启用动态压缩模块。

然后在 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 请求发送“接受编码”标头。您可以创建自定义 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.

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

【讨论】:

    【解决方案2】:

    这只是我的建议。

    您可以定义自己的 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 属性。

    更重要的是,要启用动态压缩算法,您最好将您的压缩算法传递给您的端点行为,然后该行为将压缩算法传递给您的 ClientMessageFormatter 和 DispatchMessageFormatter,以便它知道要使用哪种压缩。

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

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

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

    【讨论】:

      【解决方案3】:

      请求压缩不是服务器或客户端理解的 HTTP 标准。为此,您必须自己在客户端和服务器中完成。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-03
        • 1970-01-01
        相关资源
        最近更新 更多