Skip to main content
 首页 » 编程设计

c#之C# Web 服务的日志记录

2024年01月12日27kevingrace

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

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

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

请您参考如下方法:

我们使用 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); 
    } 
} 

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