2012-04-12 55 views
9

Tôi có một .NET 3.5 Webservice được lưu trữ trên IIS7.5.Nén GZip trong WCF WebService

Tôi có ứng dụng khách kết nối với dịch vụ web này.

tôi đã thay đổi (trong ứng dụng client) phương pháp httpWebRequest.Create thêm automaticDecompression cho GZip nhưng nó không làm việc

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; 
    } 

Bằng cách này yêu cầu được gửi một cách chính xác, câu trả lời được mã hóa trong gzip (tôi nhìn thấy nó từ Fiddler), nhưng một ngoại lệ xảy ra:

Response is not wellformed XML 

(tôi nghĩ rằng khách hàng không giải mã các câu trả lời)

Nếu tôi loại bỏ hàng này, như trong tài liệu MSDN

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

Câu trả lời là không GZip mã hóa (và trong yêu cầu rằng không có bất Accept-Encoding header)

+1

IIS sẽ có khả năng thêm hỗ trợ nén vào bất kỳ dịch vụ được lưu trữ nào. Không có cách nào để thực hiện nén GZip thông qua mã hóa tùy chỉnh. –

+1

Yeh .. ok .. và Làm cách nào để sử dụng tính năng nén GZip trong các dịch vụ web của WCF? Bởi vì tôi phải chuyển rất nhiều dữ liệu văn bản .. – AndreaCi

+0

Tôi đã đi qua toàn bộ quá trình này đau đớn khoảng 2-3 năm trở lại. Đã cố gắng tìm ra giải pháp mà tôi đã tìm thấy, nhưng không có may mắn cho đến nay. 1 trong khi đó. – leppie

Trả lời

0

Đã giải quyết !! Mã trong câu hỏi là đủ để tham khảo Dịch vụ. Nếu bạn đang sử dụng tham chiếu Web, hãy thêm vào dòng

my_service_object.EnableDecompression = true; 
0

Một cách có thể sẽ được sử dụng protobuf để đạt được nén với các dịch vụ WCF nếu bạn kiểm soát cả máy khách và máy chủ.

+0

Các protobuf là một nỗi đau lớn cho tất cả những người đã sử dụng nó, rất nhiều hạn chế là ở đây. Nhưng bất kỳ cách nào bạn không thể sử dụng nó cho một hợp đồng công cộng. –

+0

Câu hỏi cho thấy rằng họ đang kiểm soát của cả hai bên, khách hàng và máy chủ. Bạn có thể chỉ cho tôi hướng tới bài viết "đau lớn" hay một số bản tóm tắt tôi có thể hiểu rõ hơn về vấn đề là gì? –

+1

Điều đơn giản là nếu bạn gửi một bộ sưu tập trống, bạn sẽ nhận được null thay vì cùng một bộ sưu tập trống. –

4

Tôi đã thực hiện việc này để chuyển các đối tượng DataTable bằng WCF bằng DataContract. Bạn phải tạo DataContract như sau:

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

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

Sau đó, tôi đã tạo ra một chuyển đổi nhị phân sẽ tự động chuyển đổi bất kỳ đối tượng đến một mảng byte mà tôi sau đó có thể nén bằng gzip.

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); 
      } 
     } 
    } 
} 

Dump này trong dự án của bạn và gọi như thế này trong dịch vụ của bạn để nén:

dt.Data = CompressedBinaryConverter.ToByteArray(data); 

Sau đó gọi nó như thế này đứng về phía khách hàng của bạn để chuyển đổi trở lại một đối tượng:

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

có, đó là giải pháp tôi đang chuyển sang .. nhưng có một vấn đề với điều này: Nguồn và đích đối tượng là trường hợp của các lớp khác nhau (vì không gian tên khác nhau cho webservices) – AndreaCi

+0

Tôi đặt bất kỳ định nghĩa đối tượng được chia sẻ giữa máy chủ và khách hàng vào một DLL riêng biệt và tham chiếu chúng từ cả phía máy chủ và phía máy khách của tôi. Bằng cách đó bạn chỉ phải xác định/duy trì nó ở một nơi và định nghĩa của bạn là phổ quát. – MrWuf