使用WCF自定义MessageEncoder解析多部分消息

时间:2012-08-15 21:18:42

标签: wcf mtom

我正在为SOAP服务编写WCF客户端,该服务返回带有二进制数据的mime多部分结果(实际上是PDF文件)。它使用自定义消息编码器。

如果我将请求设置为单部分格式,服务似乎并不介意,因此我可以返回结果。我所看到的结果有两个问题:

  • 它似乎只返回多部分消息的第一部分。
  • 我收到的数据无法通过自定义编码器解码。

我尝试过使用MTOM绑定,但这会弄乱请求。它无法在content-type中添加“boundary”参数,因此服务器无法理解请求。

我认为我想要的是一个基本的文本SOAP请求,但是响应解码了MTOM风格。但是,我不知道如何设置它。

我找到的最接近的解决方案是:http://blogs.msdn.com/b/carlosfigueira/archive/2011/02/16/using-mtom-in-a-wcf-custom-encoder.aspx

但这对我的项目来说似乎是一次非常具有侵略性的改变。

1 个答案:

答案 0 :(得分:5)

我想出来了。首先,当我说我只使用MTOM编码器获取多部分消息的第一部分时,我是不正确的;我得到了整件事。我在调试器中查看它,底部必须在调试查看器中被剪切。根据我手工查看和解密多部分消息的经验,将其理解。

到第二点,我所要做的就是在Content-Type是多部分/相关的时候使用MTOM编码器,一切正常。如果你阅读上面引用的文章,那就是动态检测消息是多部分还是常规文本,并根据它选择合适的编码器。从本质上讲,它是一个自定义编码器,内置了文本编码器和MTOM编码器,并根据传入消息的内容类型来回切换。

我们的项目需要对响应消息进行一些后处理,然后再将其传递给主程序逻辑。因此,我们将传入的SOAP内容作为XML字符串获取,并对其进行一些XML操作。

这与文章中推荐的解决方案略有不同。本文解决方案中所需的全部内容是使用正确的编码器将消息读入System.ServiceModel.Channels.Message,并返回该消息。在我们的解决方案中,我们需要中断此过程并进行后处理。

为此,请在自定义编码器中实施以下内容:

public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
{
    //First, get the incoming message as a byte array
    var messageData = new byte[buffer.Count];
    Array.Copy(buffer.Array, buffer.Offset, messageData, 0, messageData.Length);
    bufferManager.ReturnBuffer(buffer.Array);
    //Now convert it into a string for post-processing.  Look at the content-type to determine which encoder to use.
    string stringResult;
    if (contentType != null && contentType.Contains("multipart/related"))
    {
        Message unprocessedMessageResult = this.mtomEncoder.ReadMessage(buffer, bufferManager, contentType);
        stringResult = unprocessedMessageResult.ToString();
    }
    else {
        //If it's not a multi-part message, the byte array already has the complete content, and it simply needs to be converted to a string
        stringResult = Encoding.UTF8.GetString(messageData);
    }
    Message processedMessageResult = functionToDoPostProccessing(stringResult);
    return processedMessageResult;
}