如何在DataServiceContext WCF数据服务客户端中解码gzip

本文关键字:客户端 解码 gzip 服务 数据 DataServiceContext WCF | 更新日期: 2023-09-27 18:28:00

我们有一个数据服务提供商在WCF数据服务网站上为我们提供动态压缩。我们需要利用这种压缩,因为我们每天提取的原始数据超过5Gb。使用gzip会大幅下降。

我们有一个客户端应用程序,它是使用Visual Studio 2010中的"添加服务引用"向导创建的,该向导基于DataServiceContext类。我可以使用SendingRequest事件指定Accept: gzip, deflate标头,但如何让反序列化程序在尝试解析XML之前对流进行解码?

如何在DataServiceContext WCF数据服务客户端中解码gzip

在SendingRequest中设置要获取压缩数据的相同位置,只需添加以下内容:

    e.RequestHeaders.Add("Accept-Encoding","gzip, deflate");
    ((System.Net.HttpWebRequest)e.Request).AutomaticDecompression = 
        (System.Net.DecompressionMethods.GZip | 
           System.Net.DecompressionMethods.Deflate);

参考:http://social.msdn.microsoft.com/Forums/en/adodotnetdataservices/thread/65127110-1213-45fa-a2ef-8bbd069d1294

我不知道如何使用提供的框架工具来实现这一点,所以我不得不自己动手。首先是执行实际请求的方法,该方法显示如何指定请求gzip编码的标头并解压缩结果。

  private static IEnumerable<dynamic> MakeHttpQuery(string uri)
  {
     var request = (HttpWebRequest)WebRequest.Create(new Uri(uri));
     request.Method = "GET";
     request.Accept = "application/json";
     request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip");
     try
     {
        var response = request.GetResponse();
        var contentEncoding = response.Headers[HttpResponseHeader.ContentEncoding];
        var responseStream = response.GetResponseStream();
        if (!string.IsNullOrEmpty(contentEncoding) && contentEncoding.Equals("gzip"))
        {
           responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
        }
        var json = JsonObject.Parse(responseStream);
        var d = json["d"];
        if (!d.IsArray) return new JsonArray(new[] {d}).Values;
        else return ((JsonArray) d).Values;
     }
     catch (WebException webException)
     {
        log4net.LogManager.GetLogger(typeof(ProfileMediaDataInterface)).Error(webException);
        return new JsonArray(new JsonValue[] {}).Values;
     }
  }

DynamicJson库是我不久前写的一个开源库,在这里非常方便。您可以很容易地省略Accept: application/json标头,然后返回XML。在这种情况下,类似linq-to-xml的东西也会以非常相同的方式工作。

接下来是客户端代码。这显示了如何构造要传递给MakeHttpQuery方法的URL,以及如何处理结果。

  public static List<BenchmarkListSqr> GetBenchmarkListSqr(string currencyCode)
  {
     return 
        MakeHttpQuery(
           CreateDataService()
           .BenchmarkList
           .Where(bm => bm.Currency == currencyCode)
           .ToString())
        .Select(x => new BenchmarkListSqr(
           x.Currency, 
           x.AssetClass, 
           ToNullDateTime(x.AvailableFromDate), 
           x.ID, 
           ToNullDateTime(x.InceptionDate), 
           x.Name, 
           x.Region, 
           ToNullDecimal(x.ShareID)))
        .ToList();
  }