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:传入消息具有意外的消息格式“原始”。该操作的预期消息格式为“Xml”、“Json”。这可能是因为尚未在绑定上配置 WebContentTypeMapper。有关详细信息,请参阅 WebContentTypeMapper 的文档。

修改 web 配置以使用 webMessageEncoding 而不是 gzipMessageEncoding 可以清除错误。

所以我想我想让自定义 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).  

它正在添加“原始”,因为它不知道它正在阅读什么内容类型。

在此处添加了 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 回答