我有一个 WCF webservice,我想通过实现 MessageInspector 并在 AfterReceiveRequest() 事件中记录日志来记录每个请求。
但是当我使用 SOAPUI 作为客户端向 webservice 发送请求时,复制请求消息会导致消息体仅显示 <body>... stream ...</body>
,并且无法在后续的验证中以 XML 文档的形式加载。而当我使用 WCFTestClient.exe 发送请求时,一切正常,消息被记录,请求继续进行。
我的猜测是,WCFTestClient.exe 发送的请求是带有缓冲消息体的,而来自 SOAPUI 的请求则是流式消息体?这可能吗?
是否有一种安全的方式可以编写代码,以安全地复制任一版本的消息?我尚未弄清楚如何安全地复制流式版本,因为 CreateBufferedCopy() 显然无法达到此目的。
或者,我可以配置 WCF,始终创建缓冲消息体而不是流式消息体吗?
以下是我用于记录和复制请求消息的代码:
object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
try
{
MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
request = buffer.CreateMessage();
Message copy = buffer.CreateMessage();
LogRequest(copy);
ValidateMessage(ref request);
}
catch (Exception e)
{
throw new FaultException<>()...
}
return null;
}
如果请求消息来自SOAPUI并具有流式正文,则在ValidateMessage()方法中该消息的副本无法加载到XML文档中。如果请求消息来自WCFTestClient.exe并具有缓冲正文,则可以将其加载为XML文档。
void validateMessage(ref System.ServiceModel.Channels.Message message)
{
XmlDocument bodyDoc = new XmlDocument();
//This load throws exception if request came from SOAPUI with streamed body...
bodyDoc.Load(message.GetReaderAtBodyContents());
...
}
Load()方法抛出的异常是:
System.InvalidOperationException {"指定的节点不能作为此节点的有效子级插入,因为指定的节点类型错误。"}
at System.Xml.XmlDocument.AppendChildForLoad(XmlNode newChild, XmlDocument doc) at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc) at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace) at System.Xml.XmlDocument.Load(XmlReader reader) at ...