我有一个与第三方SOAP Web服务交互的应用程序,因此我建立了服务引用,一切正常。
但是,我需要进行一些错误测试,其中我需要Web服务来响应非常特定的XML有效负载(并且由于它是第三方服务,所以我无法使其做我想做的事)。
我试图使用消息检查器的“ AfterReceiveReply”方法用所需的XML覆盖响应(该XML是从其他合法响应中捕获的,因此我知道它是有效的XML)。我的代码如下(基于https://blogs.msdn.microsoft.com/kaevans/2008/01/08/modify-message-content-with-wcf/):
public void AfterReceiveReply(ref Message reply, object correlationState)
{
// Override payload
string overrideXML = Properties.Resources.WCFOverride.Replace("---ACCOUNT_NUMBER---", "12345");
MemoryStream ms = new MemoryStream(UTF8Encoding.UTF8.GetBytes(overrideXML));
ms.Position = 0;
XmlDictionaryReaderQuotas quotas = new XmlDictionaryReaderQuotas();
XmlDictionaryReader xdr = XmlDictionaryReader.CreateBinaryReader(ms, quotas);
Message replacedMessage = Message.CreateMessage(reply.Version, null, xdr);
replacedMessage.Headers.CopyHeadersFrom(reply.Headers);
replacedMessage.Properties.CopyProperties(reply.Properties);
reply = replacedMessage;
}
代码运行时,在Message.CreateMessage(...)行上出现错误:
System.Xml.XmlException: The input source is not correctly formatted.
在那时的调试器中,我可以在MemoryStream中看到正确的XML,但是XmlDictionaryReader(xdr)似乎为空。如果尝试手动运行xdr.Read(),也会遇到相同的异常。我什至尝试了一个简单的XML结构,如:
overrideXML = "<Document></Document>";
...并且它不起作用,所以我认为我错误地设置了XML阅读器...
有人知道我在做什么错吗?
编辑: 我更新了代码以使用TextReader代替BinaryReader:
XmlDictionaryReader xdr = XmlDictionaryReader.CreateTextReader(ms.ToArray(), XmlDictionaryReaderQuotas.Max);
现在我不再遇到异常,但是更新后的回复对象看起来不正确。
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<ns:ResponseHeader xmlns:ns="[redacted]" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/">
[redacted]
</ns:ResponseHeader>
</s:Header>
<s:Body>... stream ...</s:Body>
</s:Envelope>
从字面上看,它在主体内部具有字符串值“ ... stream ...”,而不是实际的主体内容。最终结果是,响应WCF调用,我得到一个空对象,而不是预期的对象。
答案 0 :(得分:0)
“ ... stream ...”主体是红色鲱鱼。主体实际上仍然在那儿,但是reply.ToString()只是返回了本质上是一个占位符的东西。如这篇文章中所述,仍然可以通过缓冲副本访问完整消息: WCF message body showing <s:Body>... stream ...</s:Body> after modification
XmlDictionaryReader.CreateTextReader()方法似乎能够读取XML,但无法正确找到主体(使用Reply.GetBody()方法进行了测试),因此在消息返回之后对于WCF,它无法反序列化对象,因为XmlDictionaryReader认为Envelope元素是主体。
仅使用XmlReader即可正常工作,并且也更简单:
public void AfterReceiveReply(ref Message reply, object correlationState)
{
// Override payload
string overrideXML = Properties.Resources.WCFOverride.Replace("---ACCOUNT_NUMBER---", "12345");
// Create the reader
XmlReader envelopeReader = XmlReader.Create(new StringReader(overrideXML));
// Create the message using the reader
System.ServiceModel.Channels.Message replacedMessage = System.ServiceModel.Channels.Message.CreateMessage(envelopeReader, int.MaxValue, reply.Version);
replacedMessage.Headers.CopyHeadersFrom(reply.Headers);
replacedMessage.Properties.CopyProperties(reply.Properties);
reply = replacedMessage;
}