如何在WCF服务中记录原始请求

Mal*_*ric 11 asp.net wcf request operationcontext

我有几种方法的WCF服务.我想记录来自客户端的原始请求,无论它是如何发送的.一种方法接受数据作为查询字符串(严格用于遗留支持),我可以使用它来记录:

OperationContext.Current.IncomingMessageHeaders.To.AbsoluteUri
Run Code Online (Sandbox Code Playgroud)

这种情况就足够了,但其他方法允许客户端使用svcutil.exe生成的代理类将数据作为XML发送.在这种情况下,我在s:Body of中找到了我想要的数据:

OperationContext.Current.RequestContext.RequestMessage
Run Code Online (Sandbox Code Playgroud)

不幸的是,无论我尝试什么,我都无法在读取之前创建消息的缓冲副本.这是一个例子:

public CascadeResponse SendCustomer(Customer c)
    {
        Message msg = OperationContext.Current.RequestContext.RequestMessage.CreateBufferedCopy(Int32.MaxValue).CreateMessage();
        LogMessage(msg);
        // Now that the request is logged, get on with the rest
    }
Run Code Online (Sandbox Code Playgroud)

但是,在SendCustomer的第一行,我收到以下错误:

此消息不支持该操作,因为它已被读取.

这是我创建缓冲副本的关键吗?我猜我在这里犯了一些错误的东西.

编辑:

好的,所以方法现在是这样的:

public CascadeResponse SendCustomer(Message requestMessage)
    {
        Message msg = OperationContext.Current.RequestContext.RequestMessage.CreateBufferedCopy(Int32.MaxValue).CreateMessage();
        LogMessage(msg);
        // Now that the request is logged, get on with the rest        
        Customer c = msg.GetBody<Customer>();
        string clientKey = "1111"; // This should be the clientKey string passed to the function along with the customer 
        return SendLead(c, clientKey);
    }
Run Code Online (Sandbox Code Playgroud)

我的问题是我不知道如何将Customer和ClientKey作为单独的实体发送.我可以使clientKey成为Customer的一个属性(或者创建一个专门用于传递数据的自定义对象,并将Customer和ClientKey作为属性包含在内),但我想尽可能避免这种情况,因为这是遗留系统的升级,已经这样工作了.

我也无法使用svcUtil.exe来创建我的代理类 - 我假设使用上述方法签名意味着我的服务将不再通告正确的签名来发送请求?不确定这是否足够清楚 - 如果我唯一的输入方法接受Message对象,我的客户如何知道发送Customer和ClientKey?

Mal*_*ric 18

我找到了其他人也可能觉得有用的解决方案.创建MessageInspector允许您将代码附加到"AfterReceiveRequest"和"BeforeSendReply"事件,如下所示:

public class MessageInspector : IDispatchMessageInspector
{
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
        request = buffer.CreateMessage();
        LogMessage("Received:\n{0}", buffer.CreateMessage().ToString());
        return null;
    }

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
        reply = buffer.CreateMessage();
        LogMessage("Sending:\n{0}", buffer.CreateMessage().ToString());
    }
}
Run Code Online (Sandbox Code Playgroud)

这里有一个完整的教程,用于设置消息检查器.在将行为扩展名添加到app.config/web.config时,我会说要小心检查完全限定的程序集名称.

希望别人觉得这很有用.