【问题标题】:How to log the raw request in WCF service如何在 WCF 服务中记录原始请求
【发布时间】:2016-05-17 22:48:38
【问题描述】:

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

OperationContext.Current.IncomingMessageHeaders.To.AbsoluteUri

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

OperationContext.Current.RequestContext.RequestMessage

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

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
    }

但是,在 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);
    }

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

我在使用 svcUtil.exe 创建代理类时也遇到了问题 - 我假设具有上述方法签名意味着我的服务将不再宣传发送请求的正确签名?不确定这是否足够清楚 - 如果我唯一的输入法接受 Message 对象,我的客户怎么知道要发送 Customer 和 ClientKey?

【问题讨论】:

  • 为什么不能使用 WCF 中的内置跟踪功能? msdn.microsoft.com/en-us/library/ms733025.aspx
  • @DaveRead 主要是我不知道 - 这是否允许我将日志保存到数据库中?
  • 不是开箱即用,但您可以创建自己的自定义 TraceListener,详情请参阅本文:msdn.microsoft.com/en-gb/magazine/cc300790.aspx
  • 我不确定这对获取原始请求有何帮助,因为跟踪仍然需要我手动设置消息。我很可能遗漏了一些明显的东西。
  • 你一定遗漏了一些明显的东西,比如message logging

标签: asp.net wcf request operationcontext


【解决方案1】:

我找到了一个其他人可能也会觉得有用的解决方案。创建 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());
    }
}

有一个full tutorial for setting up message inspectors fo wcf here。我会说,当您将行为扩展添加到 app.config/web.config 时,请仔细检查您的完全限定程序集名称。

希望其他人觉得这很有用。

【讨论】:

    【解决方案2】:

    为了实现上述目的,您需要将方法更改为如下所示:

    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>();
        }
    

    更多关于Using Message Class的信息

    【讨论】:

    • 谢谢,这让我走上了正轨,但是在使用 svcutil.exe 创建所需的代理类时出现了一堆错误。 Cannot import wsdl:binding Cannot import wsdl:binding ... 等等此外,我不确定如何从请求正文中检索其他对象(我的示例仅包含一个对象,但实际代码具有标识客户端的附加字符串)。我会在星期一再看一次,但感谢您到目前为止的帮助。
    【解决方案3】:

    我认为你可以使用 ...ToString() 方法,它会在内部重写消息:

    string soap = OperationContext.Current.RequestContext.RequestMessage.ToString();
    

    查看ToString() 方法的内部... ;)

    【讨论】:

      【解决方案4】:

      在 VS2015 的 WCF 服务项目上,您可以右键单击 web.config 来编辑 WCF 配置。您可以在此处启用诊断以记录原始消息。

      【讨论】:

      • 您能否详细说明一下,并具体说明如何设置和设置什么?仅仅做出这样的陈述是不够的。
      猜你喜欢
      • 2012-02-24
      • 1970-01-01
      • 2023-03-10
      • 2013-01-09
      • 2016-01-27
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 2023-03-09
      相关资源
      最近更新 更多