2012-04-12 15 views
9

IIS7.5 üzerinde barındırılan bir .NET 3.5 Web hizmeti var.WCF WebService'de GZip sıkıştırması

Bu web servisine bağlanan bir istemci uygulamasına sahibim.

ben GZip için automaticDecompression eklemek için httpWebRequest.Create yöntemi (istemci uygulamasında) değişti ama istek doğru gönderilen Bu şekilde
WebRequest IWebRequestCreate.Create(Uri uri) 
    { 
     HttpWebRequest httpWebRequest = 
      Activator.CreateInstance(
       typeof(HttpWebRequest), 
       BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, 
       null, 
       new object[] { uri, null }, 
       null) as HttpWebRequest; 

     if (httpWebRequest == null) 
      return null; 

     httpWebRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate"); 
     httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; 


     return httpWebRequest; 
    } 

çalışmıyor, cevap (gzip içinde kodlanmıştır I) Fiddler'dan görüyorum ama bir istisna oluşur:

Response is not wellformed XML 

(ben gibi bu satırı kaldırırsanız istemci cevap)

deşifre etmez düşünüyorum MSDN belgelerine

httpWebRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate"); 

cevap GZip kodlanmış değildir (ve istek hiçbir orada ettiği kodlama oluyor başlığı)

+1

satırını da ekleyin. GZip sıkıştırmasını özel kodlama yoluyla uygulamak için bir yol yoktur. –

+1

Yeh .. tamam .. ve WZF web servislerinde GZip sıkıştırmasını nasıl kullanabilirim? Çünkü çok fazla metin veri aktarmam gerekiyor .. – AndreaCi

+0

Bu acı süreci yaklaşık 2-3 yıl geriye gittim. Bulduğum çözümü bulmaya çalıştım, ama şimdiye kadar hiç şans yoktu. Bu arada +1. – leppie

cevap

0

Çözüldü! Sorudaki kod, Hizmet referansları için yeterliydi. Web başvuruları kullanıyorsanız, IIS herhangi bir hizmet barındırılan için sıkıştırma desteği eklemek için bir olasılık olması gereken

my_service_object.EnableDecompression = true; 
0

hem kontrol eğer WCF hizmeti ile sıkıştırma elde etmek protobuf kullanmak olası bir yol olacaktır istemci ve sunucu.

+0

Protobuf, onu kullanan herkes için büyük bir acıdır, burada bir çok kısıtlama vardır. Ama herhangi bir şekilde kamu sözleşmesi için kullanamazsınız. –

+0

Soru, her iki tarafın, istemci ve sunucunun denetiminde olduklarını gösterir. Beni "büyük acı" makalesine yönlendirebilir misin, yoksa bazı özetler sorunların ne olduğu hakkında daha iyi bir fikre sahip olabilirim? –

+1

Basit olan, boş bir koleksiyon gönderiyorsanız, boş boş bir koleksiyon alacaksınız. –

4

Bunu DataContract ile WCF kullanarak DataTable nesnelerini aktarmak için yaptım. Sen şöyle DataContract oluşturmak zorunda:

[DataContract] 
public class WCFDataTableContract 
{ 
    [DataMember] 
    public byte[] Schema { get; set; } 

    [DataMember] 
    public byte[] Data { get; set; } 
} 

Sonra otomatik Sonra gzip kullanarak sıkıştırabilir bir bayt dizisi herhangi bir nesne dönüştürecek olan bir ikili dönüştürücü yarattı. Sonra

dt.Data = CompressedBinaryConverter.ToByteArray(data); 

Bir nesneye geri dönüştürmek için istemci tarafında böyle diyoruz: projenizde bu ve Hizmet böyle diyoruz

public static class CompressedBinaryConverter 
{ 
    /// <summary> 
    /// Converts any object into a byte array and then compresses it 
    /// </summary> 
    /// <param name="o">The object to convert</param> 
    /// <returns>A compressed byte array that was the object</returns> 
    public static byte[] ToByteArray(object o) 
    { 
     if (o == null) 
      return new byte[0]; 

     using (MemoryStream outStream = new MemoryStream()) 
     { 
      using (GZipStream zipStream = new GZipStream(outStream, CompressionMode.Compress)) 
      { 
       using (MemoryStream stream = new MemoryStream()) 
       { 
        new BinaryFormatter().Serialize(stream, o); 
        stream.Position = 0; 
        stream.CopyTo(zipStream); 
        zipStream.Close(); 
        return outStream.ToArray(); 
       } 
      } 
     } 
    } 

    /// <summary> 
    /// Converts a byte array back into an object and uncompresses it 
    /// </summary> 
    /// <param name="byteArray">Compressed byte array to convert</param> 
    /// <returns>The object that was in the byte array</returns> 
    public static object ToObject(byte[] byteArray) 
    { 
     if (byteArray.Length == 0) 
      return null; 

     using (MemoryStream decomStream = new MemoryStream(byteArray), ms = new MemoryStream()) 
     { 
      using (GZipStream hgs = new GZipStream(decomStream, CompressionMode.Decompress)) 
      { 
       hgs.CopyTo(ms); 
       decomStream.Close(); 
       hgs.Close(); 
       ms.Position = 0; 
       return new BinaryFormatter().Deserialize(ms); 
      } 
     } 
    } 
} 

Dökümü sıkıştırmak için

dt = (DataTable)CompressedBinaryConverter.ToObject(wdt.Data); 
+0

evet, şu anki çözümüm ... ama bununla ilgili bir sorun var: Kaynak ve hedef nesneler farklı sınıfların örnekleridir (webservices için farklı ad alanlarından dolayı) – AndreaCi

+0

Sunucuyla paylaşılan nesne tanımlarını koyarım. istemciyi ayrı bir DLL'ye alıp hem Sunucu hem de İstemci tarafımdan başvuruda bulundu. Bu şekilde sadece bir yerde tanımlamanız/sürdürmeniz ve tanımlarınız evrenseldir. – MrWuf