我们正在使用网络服务。我们使用 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);
}
}
它没有经过性能/压力测试,但它似乎运行良好 - 希望流复制的完成方式应该减轻任何性能影响。
