在Silverlight中向WCF添加压缩的最简单方法是什么?

时间:2020-03-05 18:39:25  来源:igfitidea点击:

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

该请求确实具有"接受编码:gzip,deflate"。WCF服务gzip(或者以其他方式压缩)响应有什么办法吗?

我确实找到了此链接,但是对于应该立即使用的恕我直言处理的功能,似乎确实有些复杂。

首先,我将System.IO.Compression标记为解决方案,因为我永远无法"似乎"使IIS7动态压缩正常工作。好吧,事实证明:

  • IIS7上的动态压缩一直在工作。仅仅是Nikhil的IE的Web开发者帮助器插件没有显示出它的工作原理。我的猜测是,由于SL将Web服务调用移交给了浏览器,因此浏览器"在幕后"处理了它,而Nikhil的工具从未看到压缩的响应。我能够通过使用Fiddler来确认这一点,它监视浏览器应用程序外部的流量。在提琴手中,响应实际上是gzip压缩了!!
  • System.IO.Compression解决方案的另一个问题是Silverlight CLR中不存在System.IO.Compression。

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

解决方案

回答

最近在执行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);

对我来说很好。

回答

如果我们使用的是IIS7,请查看"压缩模块"。这使我们可以配置对服务器的HTTP请求的压缩。

回答

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

请参阅Pablo M. Cibraro的WS-Compression for WCF

或者,尝试使用Microsoft的GZip编码器示例,该示例"创建使用System.IO.Compression.GZipStream类压缩输出WCF消息的编码器通道"

回答

还应注意,除了为站点启用压缩之外,我们可能还需要在<httpCompression> <dynamicTypes>部分的" applicationHost.config"中添加mime类型:

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

如果某些动态响应未压缩(有些压缩),则可能是mime类型的问题。使用Fiddler来获取与请求关联的细节。失败的请求跟踪可能对确定IIS是否甚至尝试压缩响应很有用。如果正确配置了压缩,则会在跟踪输出的完整跟踪部分中看到" NO_MATCHING_CONTENT_TYPE"。