我有一个wcf客户端,我需要记录来自外部服务的请求和响应。
我可以在我的自定义消息编码器中执行此操作,但我需要一些相关ID来创建名为这样的文件:id_request.xml
和id_response.xml
。
所以我的问题是如何将一些字符串从ReadMessage
传递给WriteMessage
?
我尝试使用IClientMessageInspector
的实现,但WCF在编码之前调用BeforeSendRequest
并且消息不完整。此外,我无法在AfterReceiveReply
中保存请求和响应,因为在我发送请求之后但在收到响应之前,我的应用程序(或外部服务)可能会崩溃。
答案 0 :(得分:1)
我找到了一个适合我的解决方案。在我IClientMessageInspector
的实现中,我创建了类CorrelationObject
:
class CorrelationObject
{
public string RequestFileName { get; set; }
public string ResponseFileName { get; set; }
}
然后在BeforeSendRequest
中生成具有相同Id作为前缀的唯一名称,并将该关联对象存储在请求属性中:
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var id = Guid.NewGuid();
var correlationObject = new CorrelationObject
{
RequestFileName = $"{id:N}_request.xml",
ResponseFileName = $"{id:N}_response.xml"
};
request.Properties.Add("CorrelationObject", correlationObject);
return correlationObject;
}
之后,WCF将我的请求传递给消息编码器
public override ArraySegment<byte> WriteMessage(Message message,
int maxMessageSize, BufferManager bufferManager, int messageOffset)
{
// encoding and signing
var encodedMessage = string.Empty;
var correaltionObject = (CorrelationObject) message.Properties["CorrelationObject"];
File.WriteAllText(correaltionObject.RequestFileName, encodedMessage);
}
此时我保存了我的请求。为了保存响应,我在消息编码器中执行了以下操作:
public override Message ReadMessage(ArraySegment<byte> buffer,
BufferManager bufferManager, string contentType)
{
var content = Encoding.UTF8.GetString(buffer.ToArray());
var response = innerEncoder.ReadMessage(buffer, bufferManager, contentType);
response.Properties.Add("RawMessage", content);
// some other staff here..
}
现在WCF在我的消息检查器中调用AfterReceiveReply
public void AfterReceiveReply(ref Message reply, object correlationState)
{
var correlationObject = (CorrelationObject) correlationState;
File.WriteAllText(correlationObject.ResponseFileName,
reply.Properties["RawMessage"].ToString());
}
现在,两个文件都以相同的前缀保存。