0

REST サービスの POST 呼び出しが与えられた場合:

 [WebInvoke] // POST
 string PostItem(PostItemContract contract);

これは、カスタム バインディング (web.config) 内でカスタム gzip エンコーダーを使用します。

  <customBinding>
    <binding name="customHttpGzipBindingConfig">          
      <!-- Normally would use binaryMessageEncoding, textMessageEncoding or webMessageEncoding here  -->          
      <gzipMessageEncoding innerMessageEncoding="webMessageEncoding"/>          
      <httpTransport ...>        
    </binding>        
  </customBinding>     

エラーが発生します:

InvalidOperationException: 受信メッセージに予期しないメッセージ形式 'Raw' があります。この操作で想定されるメッセージ形式は、'Xml'、'Json' です。これは、バインディングで WebContentTypeMapper が構成されていないことが原因である可能性があります。詳細については、WebContentTypeMapper のドキュメントを参照してください。

gzipMessageEncoding の代わりに webMessageEncoding を使用するように Web 構成を変更すると、エラーがクリアされます。

したがって、カスタム gzipMessageEncoding を webMessageEncoding であるかのように動作させたいと考えています。

私は最初にクラス GzipWebContentTypeMapper を作成しました: WebContentTypeMapper GetMessageFormatForContentType() は WebContentFormat.Xml を返すだけです。

その後、MSDN サンプルに基づいたエンコーダーにいくつかの変更が加えられました。

カスタム メッセージ エンコーダー: 圧縮エンコーダー

class GZipMessageEncoder : MessageEncoder
{   
   public override bool IsContentTypeSupported(string contentType)
   {
       // A BP here says it is returning true, this is where the
       // custom GetMessageFormatForContentType() is getting called.

       return innerEncoder.IsContentTypeSupported(contentType);
   }     
   // ...
}

public class GZipMessageEncodingElement : BindingElementExtensionElement
{        
    public override Type BindingElementType
    {
       get { return typeof(WebMessageEncodingBindingElement); } // just to see
    }
    public override void ApplyConfiguration(BindingElement bindingElement)
    {                        
        GZipMessageEncodingBindingElement binding = (GZipMessageEncodingBindingElement)bindingElement;

        WebMessageEncodingBindingElement element = new WebMessageEncodingBindingElement();
        // responsible for mapping from Content-Type to WCF xml/json/raw/default formats.
        element.ContentTypeMapper = new GzipWebContentTypeMapper();
        binding.InnerMessageEncodingBindingElement = element;                              
    }
    // ...
}

デバッガーは次のことを示しています。

GzipWebContentTypeMapper は実際に呼び出され、WebContentFormat.Xml を返します。

GZipMessageEncoder.IsContentTypeSupported は true を返します。

フォーマットを明示的に設定しても機能しません (?):

[WebInvoke(RequestFormat=WebMessageFormat.Xml)] 
string PostItem(PostItemContract contract);

web.config 内で、カスタム gzip エンコーダーの前後に webMessageEncoding を追加しようとしましたが、役に立ちませんでした。

GZipMessageEncoder.IsContentTypeSupported が true を返した後に何が起こるか考えていますか?

GzipWebContentTypeMapper (WebContentFormat.Xml を正常に返す) の結果はどこに保存され、どのように無視されるのでしょうか?

4

1 に答える 1

0

問題は、 ContentType がエンコーダー内の innerEncoder に渡されていないことでした。

ここで、 message.Property[] がキー付きのメッセージに追加されます

WebBodyFormatMessageProperty.Name 

と価値

new WebBodyFormatMessageProperty(WebContentFormat).  

読み取っているコンテンツの種類がわからないため、「Raw」を追加していました。

ここに contentType 引数を追加しました:

class GZipMessageEncoder : MessageEncoder
{
   // ...
   ReadMessage(ArraySegment<byte> buffer, ...)  
   { 
      //...
      _innerEncoder.ReadMessage(decompressedBuffer, bufferManager, **contentType**);
   }

   ReadMessage(Stream stream, ...)
   { 
      //...
      _innerEncoder.ReadMessage(stream, maxSizeOfHeaders, **contentType**);
   }
}
于 2013-01-10T18:46:48.637 に答える