如何在Silverlight中为WCF添加压缩的最简单方式是什么?

24
我有一个使用Silverlight 2 beta 2的应用程序,它访问一个WCF Web服务。因此,它目前只能使用basicHttp绑定。Web服务将返回相当大量的XML数据。从带宽使用的角度来看,这似乎非常浪费,因为如果压缩响应,则响应大小将减小5倍(实际上我将响应粘贴到txt文件中并压缩它)。
请求确实具有"Accept-Encoding: gzip, deflate" - 是否有任何方法可以使WCF服务gzip(或以其他方式压缩)响应?
我找到了链接,但对于应该由开箱即用处理的功能来说,它似乎有点复杂。
好的-起初我标记使用System.IO.Compression作为答案,因为我似乎永远无法使IIS7动态压缩工作。嗯,事实证明:
  1. IIS7上的动态压缩一直都在工作。只是Nikhil的Web Developer Helper插件没有显示它正在工作。我的猜测是,由于SL将Web服务调用交给了浏览器,所以浏览器在“底层”处理它,并且Nikhil的工具从未看到压缩的响应。我通过使用监视浏览器应用程序外部流量的Fiddler来确认了这一点。在fiddler中,响应实际上被gzip压缩了!

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

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


动态压缩仅适用于某些请求(即IIS认为经常调用的请求)。因此,这是一个不错的功能,但您无法对其进行控制。当用户登录时,我的调用非常大,但它只发生一次,并且没有被压缩。 - Boppity Bop
4个回答

12

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

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

或者,您可以尝试使用Microsoft的GZip编码器示例,该示例“创建一个编码器通道,该通道使用System.IO.Compression.GZipStream类来压缩传出的WCF消息”。


3
唯一的注意事项是,Silverlight 2 完全不支持 WS 绑定,只支持基本的 basicHttp 绑定。 - caryden

11

最近我在做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);

我对此感到满意。

1
请注意,在Silverlight 2 CLR中不提供GZipStream。DimeBrain在这里实现了SharpZipLib:http://dimebrain.com/2008/06/compression-i-1.html - russau

10
如果您正在使用IIS7,请看一下压缩模块。这可以让您对发送到您的服务器的HTTP请求进行压缩配置。

这里有一些注意事项:我的工作代理会删除接受gzip头(真是令人困惑,对吧?)。而且你只需要压缩发送给客户端的数据。 - russau

3
需要注意的是,除了在站点上启用压缩外,您可能还需要将MIME类型添加到<httpCompression><dynamicTypes>部分下的applicationHost.config中:
<add mimeType="application/soap+msbin1" enabled="true" />

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

这对我有用。但是需要注意的是,您必须在C:\ Windows \ System32 \ inetsrv \ config \ applicationHost.config文件中设置此设置,因为web.config设置将被忽略。 一旦更改了这个设置,它立即开始工作。 - R4cOOn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接