记录C#Web服务

时间:2011-02-24 02:50:11

标签: c# logging asmx

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

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

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

1 个答案:

答案 0 :(得分:0)

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

整个系统由两个类组成,一个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);
    }
}

它没有经过性能/压力测试,但它看起来很好 - 希望完成流复制的方式可以减轻任何性能影响。