【问题标题】:What is the easiest way to add compression to WCF in Silverlight?在 Silverlight 中向 WCF 添加压缩的最简单方法是什么?
【发布时间】:2008-08-13 16:08:43
【问题描述】:

我有一个可以访问 WCF Web 服务的 silverlight 2 beta 2 应用程序。正因为如此,它目前只能使用 basicHttp 绑定。 Web 服务将返回相当大量的 XML 数据。从带宽使用的角度来看,这似乎是相当浪费的,因为响应,如果压缩,会小 5 倍(我实际上将响应粘贴到一个 txt 文件并压缩它。)。

请求确实有“Accept-Encoding: gzip, deflate” - 有没有办法让 WCF 服务 gzip(或以其他方式压缩)响应?

我确实找到了这个link,但对于应该开箱即用的功能来说,恕我直言,它确实看起来有点复杂。

好的 - 起初我使用 System.IO.Compression 标记解决方案作为答案,因为我永远无法“似乎”让 IIS7 动态压缩工作。好吧,事实证明:

  1. IIS7 上的动态压缩一直在工作。只是 Nikhil 的 IE Web Developer Helper 插件没有显示它工作。我的猜测是,由于 SL 将 Web 服务调用交给浏览器,浏览器会“在幕后”处理它,而 Nikhil 的工具永远不会看到压缩响应。我能够通过使用监视浏览器应用程序外部流量的 Fiddler 来确认这一点。在 fiddler 中,响应实际上是 gzip 压缩的!!

  2. System.IO.Compression 解决方案的另一个问题是 Silverlight CLR 中不存在 System.IO.Compression。

所以从我的角度来看,在 Silverlight 中启用 WCF 压缩的最简单方法是在 IIS7 中启用动态压缩并且根本不编写任何代码。

【问题讨论】:

  • 动态压缩仅适用于某些请求(即那些被 IIS 视为经常调用的请求)。所以这是一个很好的功能,但你无法控制它。当用户登录时,我的通话量非常大。但它每天都会发生一次。而且它没有被压缩。

标签: wcf silverlight compression gzip


【解决方案1】:

WS-Compression for WCF 允许您在绑定上配置压缩。

参见 Pablo M. Cibraro 的 WS-Compression for WCF

或者,试试微软的GZip Encoder Sample,它“创建一个使用 System.IO.Compression.GZipStream 类来压缩传出 WCF 消息的编码器通道”

【讨论】:

  • 一个警告是silverlight 2根本不支持WS-bindings,只支持basicHttp bindings。
【解决方案2】:

我最近在做 WCF 项目时没有看到 WCF 进行压缩的原生方式。我刚刚使用了 System.IO.Compression 命名空间并制作了一个快速压缩器。这是我使用的代码

public static class CompressedSerializer
{
    /// <summary>
    /// Decompresses the specified compressed data.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="compressedData">The compressed data.</param>
    /// <returns></returns>
    public static T Decompress<T>(byte[] compressedData) where T : class
    {
        T result = null;
        using (MemoryStream memory = new MemoryStream())
        {
            memory.Write(compressedData, 0, compressedData.Length);
            memory.Position = 0L;

            using (GZipStream zip= new GZipStream(memory, CompressionMode.Decompress, true))
            {
                zip.Flush();
                var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                result = formatter.Deserialize(zip) as T;
            }
        }

        return result;
    }

    /// <summary>
    /// Compresses the specified data.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="data">The data.</param>
    /// <returns></returns>
    public static byte[] Compress<T>(T data)
    {
        byte[] result = null;
        using (MemoryStream memory = new MemoryStream())
        {
            using (GZipStream zip= new GZipStream(memory, CompressionMode.Compress, true))
            {
                var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                formatter.Serialize(zip, data);
            }

            result = memory.ToArray();
        }

        return result;
    }
}

然后我只是让我的服务接受一个字节数组作为输入,就像这样

void ReceiveData(byte[] data);

对我来说效果很好。

【讨论】:

【解决方案3】:

如果您使用的是 IIS7,请查看Compression Module。这允许您为对服务器的 HTTP 请求配置压缩。

【讨论】:

  • 这里有一些警告:我的工作代理删除了接受 gzip 标头(wtf,对吗?)。而且您只是在压缩发送到客户端的数据。
【解决方案4】:

还应注意,除了为站点启用压缩之外,您可能还需要将 mime 类型添加到 applicationHost.config 下的 &lt;httpCompression&gt;&lt;dynamicTypes&gt; 部分:

<add mimeType="application/soap+msbin1" enabled="true" />

如果某些动态响应没有被压缩(有些是),则可能是 mime 类型问题。使用 Fiddler 获取与请求相关的细节。失败的请求跟踪可能有助于确定 IIS 是否甚至尝试压缩响应。如果压缩配置正确,您将在跟踪输出的完整跟踪部分看到NO_MATCHING_CONTENT_TYPE

【讨论】:

  • 这对我有用。但是应该注意,您必须在 C:\Windows\System32\inetsrv\config\applicationHost.config 文件中设置此设置,因为 web.config 设置被忽略。一旦我改变了它就立即工作。
猜你喜欢
  • 1970-01-01
  • 2010-09-12
  • 2016-01-26
  • 2015-02-11
  • 2020-07-28
  • 1970-01-01
  • 2012-05-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多