如何在DataServiceContext WCF数据服务客户端中解码gzip
本文关键字:客户端 解码 gzip 服务 数据 DataServiceContext WCF | 更新日期: 2023-09-27 18:28:00
我们有一个数据服务提供商在WCF数据服务网站上为我们提供动态压缩。我们需要利用这种压缩,因为我们每天提取的原始数据超过5Gb。使用gzip会大幅下降。
我们有一个客户端应用程序,它是使用Visual Studio 2010中的"添加服务引用"向导创建的,该向导基于DataServiceContext类。我可以使用SendingRequest
事件指定Accept: gzip, deflate
标头,但如何让反序列化程序在尝试解析XML之前对流进行解码?
在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();
}