C# Web 服务的日志记录

发布于 2024-10-19 02:48:06 字数 152 浏览 2 评论 0原文

我们正在使用网络服务。我们使用 wsdl.exe 生成客户端代理。

我们如何保留代理向 Web 服务提供商发送和从 Web 服务提供商接收的所有底层 XML 文件?

目的是在系统出现故障和出现争议时,通过表明我们确实以良好的格式发送了所有参数来保护我们自己。

We are consuming web services. We use wsdl.exe to generate the client proxy.

How do we keep all the underlying XML files the proxy sends to and receives from the web services provider?

The purpose is to protect ourselves by showing we did have send all the parameters in good format when system malfunctions and disputes arise.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

甜宝宝 2024-10-26 02:48:07

我们使用 SoapExtension 来做到这一点在发出 Web 服务请求的应用程序中。

整个系统由两个类组成,一个 CopyStream 类,它提供了在读/写时将流的内容复制到第二个流的能力,以及一个 SoapLogger > 拦截应用程序中所有 SOAP 请求和响应并将它们记录到文件中的类。

您只需要在您的 app.config 文件中注册它:

<configuration>
  <system.web>
    <webServices>
      <soapExtensionTypes>
        <add type="MyNamespace.SoapLogger, MyAssembly" priority="3" group="High" />
      </soapExtensionTypes>
    </webServices>
  </system.web>
</configuration>

对代码的一大块表示歉意,但它是:

/// <summary>
/// Extension to allow logging of SOAP request and response xml.
/// </summary>
public class SoapLogger : SoapExtension
{
    private MemoryStream copyStream;

    public override Stream ChainStream(Stream stream)
    {
        this.copyStream = new MemoryStream();
        return new CopyStream(stream, copyStream);
    }

    public override object GetInitializer(Type serviceType)
    {
        return null;
    }

    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
    {
        return null;
    }

    public override void Initialize(object initializer)
    {

    }

    public override void ProcessMessage(SoapMessage message)
    {
        switch (message.Stage)
        {
            case SoapMessageStage.AfterSerialize:
            case SoapMessageStage.AfterDeserialize:
                Log(message);
                break;
        }
    }

    private void Log(SoapMessage message)
    {
        string messageType;
        if (message.Stage == SoapMessageStage.AfterDeserialize)
        {
            messageType = message is SoapServerMessage ? "SoapRequest" : "SoapResponse";
        }
        else
        {
            messageType = message is SoapServerMessage ? "SoapResponse" : "SoapRequest";
        }

        StreamReader reader = new StreamReader(new MemoryStream(this.copyStream.ToArray()));
        Logger.Log(string.Format(
            "{0} ({1}):\r\n{2}",
            messageType,
            message.MethodInfo.Name,
            reader.ReadToEnd()
        ));
    }
}

/// <summary>
/// Implementation of a stream that wraps an existing stream while copying anything written
/// or read to another stream.
/// </summary>
public class CopyStream : Stream
{
    public Stream BaseStream
    {
        get
        {
            return this.baseStream;
        }
    }
    private Stream baseStream;

    public Stream OtherStream
    {
        get
        {
            return this.otherStream;
        }
    }
    private Stream otherStream;

    public CopyStream(Stream BaseStream, Stream OtherStream)
    {
        if (BaseStream == null)
        {
            throw new ArgumentNullException("BaseStream");
        }
        if (OtherStream == null)
        {
            throw new ArgumentNullException("OtherStream");
        }

        this.baseStream = BaseStream;
        this.otherStream = OtherStream;
    }

    public override bool CanRead
    {
        get
        {
            return this.BaseStream.CanRead;
        }
    }

    public override bool CanSeek
    {
        get
        {
            return this.BaseStream.CanSeek;
        }
    }

    public override bool CanWrite
    {
        get
        {
            return this.BaseStream.CanWrite;
        }
    }

    public override void Flush()
    {
        this.BaseStream.Flush();
    }

    public override long Length
    {
        get
        {
            return this.BaseStream.Length;
        }
    }

    public override long Position
    {
        get
        {
            return this.BaseStream.Position;
        }
        set
        {
            this.BaseStream.Position = value;
        }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        int returnValue = BaseStream.Read(buffer, offset, count);
        this.otherStream.Write(buffer, offset, returnValue);
        return returnValue;
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        try
        {
            this.OtherStream.Seek(offset, origin);
        }
        catch { }
        return BaseStream.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
        try
        {
            this.OtherStream.SetLength(value);
        }
        catch { }
        this.BaseStream.SetLength(value);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        try
        {
            this.OtherStream.Write(buffer, offset, count);
        }
        catch { }
        this.BaseStream.Write(buffer, offset, count);
    }
}

它没有经过性能/压力测试,但它似乎保持得很好 - 希望 完成流复制的方式应该可以减轻任何性能影响。

We did just that using a SoapExtension in the application making the web service requests.

The entire system consisted of two classes, a CopyStream class that provided the ability to duplicate the contents of a stream to a second stream as it is read / written to, and a SoapLogger class that intercepts all SOAP requests and responses in the application and logs them to a file.

You just need to register it in your app.config file:

<configuration>
  <system.web>
    <webServices>
      <soapExtensionTypes>
        <add type="MyNamespace.SoapLogger, MyAssembly" priority="3" group="High" />
      </soapExtensionTypes>
    </webServices>
  </system.web>
</configuration>

Apologies for the big blob of code, but here it is:

/// <summary>
/// Extension to allow logging of SOAP request and response xml.
/// </summary>
public class SoapLogger : SoapExtension
{
    private MemoryStream copyStream;

    public override Stream ChainStream(Stream stream)
    {
        this.copyStream = new MemoryStream();
        return new CopyStream(stream, copyStream);
    }

    public override object GetInitializer(Type serviceType)
    {
        return null;
    }

    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
    {
        return null;
    }

    public override void Initialize(object initializer)
    {

    }

    public override void ProcessMessage(SoapMessage message)
    {
        switch (message.Stage)
        {
            case SoapMessageStage.AfterSerialize:
            case SoapMessageStage.AfterDeserialize:
                Log(message);
                break;
        }
    }

    private void Log(SoapMessage message)
    {
        string messageType;
        if (message.Stage == SoapMessageStage.AfterDeserialize)
        {
            messageType = message is SoapServerMessage ? "SoapRequest" : "SoapResponse";
        }
        else
        {
            messageType = message is SoapServerMessage ? "SoapResponse" : "SoapRequest";
        }

        StreamReader reader = new StreamReader(new MemoryStream(this.copyStream.ToArray()));
        Logger.Log(string.Format(
            "{0} ({1}):\r\n{2}",
            messageType,
            message.MethodInfo.Name,
            reader.ReadToEnd()
        ));
    }
}

/// <summary>
/// Implementation of a stream that wraps an existing stream while copying anything written
/// or read to another stream.
/// </summary>
public class CopyStream : Stream
{
    public Stream BaseStream
    {
        get
        {
            return this.baseStream;
        }
    }
    private Stream baseStream;

    public Stream OtherStream
    {
        get
        {
            return this.otherStream;
        }
    }
    private Stream otherStream;

    public CopyStream(Stream BaseStream, Stream OtherStream)
    {
        if (BaseStream == null)
        {
            throw new ArgumentNullException("BaseStream");
        }
        if (OtherStream == null)
        {
            throw new ArgumentNullException("OtherStream");
        }

        this.baseStream = BaseStream;
        this.otherStream = OtherStream;
    }

    public override bool CanRead
    {
        get
        {
            return this.BaseStream.CanRead;
        }
    }

    public override bool CanSeek
    {
        get
        {
            return this.BaseStream.CanSeek;
        }
    }

    public override bool CanWrite
    {
        get
        {
            return this.BaseStream.CanWrite;
        }
    }

    public override void Flush()
    {
        this.BaseStream.Flush();
    }

    public override long Length
    {
        get
        {
            return this.BaseStream.Length;
        }
    }

    public override long Position
    {
        get
        {
            return this.BaseStream.Position;
        }
        set
        {
            this.BaseStream.Position = value;
        }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        int returnValue = BaseStream.Read(buffer, offset, count);
        this.otherStream.Write(buffer, offset, returnValue);
        return returnValue;
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        try
        {
            this.OtherStream.Seek(offset, origin);
        }
        catch { }
        return BaseStream.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
        try
        {
            this.OtherStream.SetLength(value);
        }
        catch { }
        this.BaseStream.SetLength(value);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        try
        {
            this.OtherStream.Write(buffer, offset, count);
        }
        catch { }
        this.BaseStream.Write(buffer, offset, count);
    }
}

Its not been performance / stress tested, but it seems to be holding up just fine - hopefully the way that the stream copying is done should mitigate any performance impact.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文