2012-04-12 57 views
9

私はIIS7.5でホストされている.NET 3.5 Webサービスを持っています。WCF WebServiceでのGZip圧縮

私はこのWebサービスに接続するクライアントアプリケーションを持っています。

要求が正しく送信されて、答えは(GZIPでエンコードされた私は、(クライアントアプリケーション内)でGZipためautomaticDecompressionを追加するhttpWebRequest.Create方法を変更したが、それはこのように

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

が動作していません私は)フィドラーからそれを見るが、例外が発生します。

Response is not wellformed XML 

(私はクライアントが答えを復号しないと思います)

私はこの行を削除する場合は、のようにMSDNのドキュメント

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

答えは、GZIPエンコードされません(とリクエストにACCEPT-ENCODINGをヘッダにはあります)あなたは、両方のコントロールしている場合

+1

IISはホストされているサービスに圧縮サポートを追加する可能性があります。カスタムコーディングを通じてGZip圧縮を実装する方法はありません。 –

+1

Yeh .. ok ..そしてWCF WebサービスでGZip圧縮を使用するにはどうすればいいですか?私は多くのテキストデータを転送しなければならないので。 – AndreaCi

+0

私は約2〜3年前にこの痛みを伴うプロセスを行った。私が見つけた解決策を見出そうとしていたが、これまでのところ運がなかった。その間に+1。 – leppie

答えて

0

解決済み! 問題のコードはサービス参照のために十分でした。 Web参照を使用している場合は、行も追加してください。

my_service_object.EnableDecompression = true; 
0

1つの可能な方法は、WCFサービスで圧縮を達成するためにprotobufを使用することですクライアントとサーバー。

+0

protobufはそれを使用している人にとって大きな苦痛であり、多くの制限があります。しかし、あなたは公的契約のためにそれを使うことはできません。 –

+0

この質問は、クライアントとサーバーの両方を制御していることを示しています。 「大きな痛み」の記事またはいくつかの要約に向かって私を指摘できますか?問題が何であるかをより良く知ることができますか? –

+1

単純なのは、空のコレクションを送信する場合、同じ空のコレクションではなくヌルを受け取ることです。 –

4

私はDataContractでWCFを使用してDataTableオブジェクトを転送するためにこれを行っています。あなたは次のようにのDataContractを作成する必要があります。

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

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

その後、私は自動的に私は、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); 
      } 
     } 
    } 
} 

プロジェクトでこれをダンプし、圧縮するあなたのサービスでは以下のように呼び出す:

dt.Data = CompressedBinaryConverter.ToByteArray(data); 

その後バックオブジェクトに変換するために、クライアント側でこのようにそれを呼び出す:

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

はい、それは私が動いている解決策ですが、これには問題があります。ソースオブジェクトと宛先オブジェクトは異なるクラスのインスタンスです(Webサービスの異なる名前空間のため) – AndreaCi

+0

サーバとクライアントを別のDLLに変換し、私のサーバー側とクライアント側の両方からそれらを参照します。そうすれば、あなたは一箇所で定義/維持するだけで、定義は普遍的です。 – MrWuf