WCF:如何手动记录原始 xml 消息内容?

WCF: How to log raw xml message contents manually?

我有一个使用 WCF 调用 SOAP API 的简单 classic ASP 网站。 为了进行调试,我需要将 XML 消息内容手动记录到单独的日志文件中。

例如,12/23/18_34.txt 文件包含在 12/23 18:34 发送的 XML 请求。 我阅读了许多记录 WCF XML 消息的文章并找到了这两种方法。

  1. 使用 MessageLogging 功能。
  2. 使用 IClientMessageInspector。

我可以使用第一种方法进行日志记录,但是这样做我无法将消息内容保存到具有特定名称的单独文件中。 所以我尝试了第二种方法,但它不起作用,我找不到问题所在。

由于当前项目是一个classic ASP网站并且没有命名空间,我不知道如何在web.config文件中设置type属性的值。 我设法通过创建一个包含 BehaviorExtensionElement 的单独 dll 文件来添加它,并将其复制到当前项目的 Bin 文件夹。

<add name="logXmlBehavior" type="MessageLogger.MessageLoggerBehaviorExtensionElement, MessageLogger, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
public class MessageLogger : IClientMessageInspector
    {
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
            reply = buffer.CreateMessage();

            var fileName = DateTime.Now.ToString("dd_HHmm");
            System.IO.File.WriteAllText($"C:/Logs/Symmetry/{fileName}_response.txt", buffer.CreateMessage().ToString());
        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
            request = buffer.CreateMessage();

            var fileName = DateTime.Now.ToString("dd_HHmm");
            System.IO.File.WriteAllText($"C:/Logs/Symmetry/{fileName}_post.txt", buffer.CreateMessage().ToString());
            return null;
        }
    }

这是我的 MessageLogger class,但它不记录任何内容。

如何在没有单独的 DLL 的情况下将 BehaviorExtensionElement 添加到 classic ASP 网站? 为什么我当前的记录器不工作?

PS: 该网站使用 IIS 托管。

你的代码片段看起来没有问题。请参考我的例子。
MessageLogger class.

    public class ClientMessageLogger : IClientMessageInspector
    {
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            string displayText = $"the client has received the reply:\n{reply}\n";
            Console.Write(displayText);
        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            string displayText = $"the client send request message:\n{request}\n";
            Console.WriteLine(displayText);
            return null;
        }
}

要应用于客户端服务端点的端点行为。

public class AuthBehavior : BehaviorExtensionElement, IEndpointBehavior
    {
        public override Type BehaviorType => typeof(AuthBehavior);
        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }
        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            ClientMessageLogger inspector = new ClientMessageLogger();
            clientRuntime.ClientMessageInspectors.Add(inspector);
        }
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
        }
        public void Validate(ServiceEndpoint endpoint)
        {
        }
        protected override object CreateBehavior()
        {
            return new AuthBehavior();
        }
    }

然后我在扩展部分注册端点行为并将其应用于自动生成的客户端服务端点。

    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IService" />
            </basicHttpBinding>
        </bindings>
        <client>
          <!--apply it on the endpoint-->
            <endpoint address="http://localhost:1300/" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_IService" contract="ServiceReference1.IService"
                name="BasicHttpBinding_IService" behaviorConfiguration="authBehavior" />
        </client>
      <behaviors>
        <endpointBehaviors>
          <behavior name="authBehavior">
            <authbehavior />
          </behavior>
        </endpointBehaviors>
      </behaviors>
      <extensions>
        <behaviorExtensions>
          <!--like yours, namespace.class,assembly-->
          <add name="authbehavior" type="Client3.AuthBehavior,Client3,Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        </behaviorExtensions>
      </extensions>
</system.serviceModel>

最终,控制台应用程序在向服务器发送请求时正确记录了消息。

ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
        //client.Endpoint.EndpointBehaviors.Add(new AuthBehavior());
        try
        {
            Console.WriteLine(client.SayHello());
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }

结果。

此外,我认为 WCF 跟踪也可以完成记录通信消息的任务。只需添加以下配置,检查 bin 文件夹中的 mylogs.svclog 文件。

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add type="System.Diagnostics.XmlWriterTraceListener" name="xmlLog" initializeData="myLogs.svclog"/>
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IService" />
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://10.157.13.70:1300/" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IService" contract="ServiceReference1.IService"
        name="BasicHttpBinding_IService" />
    </client>
    <diagnostics>
      <messageLogging logEntireMessage="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="false"/>
    </diagnostics>
  </system.serviceModel>

如果有什么我可以帮忙的,请随时告诉我。