在c# 2.0的WebService中,可以使用SoapExtension来扩展WebService的功能。
在日常接口的调测中,尤其是不同平台的WebService接口调测中,很容易出现请求错误或者请求参数为空,或者复杂请求参数的属性为空的情况。这样,就需要查看传递的xml报文。
当然,我们可以使用类似wireshark之类的抓包工具来看具体的传输东西,但是那样略嫌麻烦。在微软的官网,就给了一个TraceExtension的例子,继承自SoapExtension,用来记录传入和传出的报文。
示例如下(
注意要看下面的备注及说明):
1.先创建SoapExtension.cs,新建一个App_Code文件夹,把cs文件放在这个目录下
///SoapExtension.cs
public class TraceExtension : SoapExtension
{
private readonly string FILEPREFIX = "D:\\logs";
Stream oldStream;
Stream newStream;
string filename;
// Save the Stream representing the SOAP request or SOAP response into
// a local memory buffer.
public override Stream ChainStream(Stream stream)
{
oldStream = stream;
newStream = new MemoryStream();
return newStream;
}
// When the SOAP extension is accessed for the first time, the XML Web
// service method it is applied to is accessed to store the file
// name passed in, using the corresponding SoapExtensionAttribute.
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
return ((TraceExtensionAttribute)attribute).Filename;
}
// The SOAP extension was configured to run using a configuration file
// instead of an attribute applied to a specific XML Web service
// method.
public override object GetInitializer(Type WebServiceType)
{
// Return a file name to log the trace information to, based on the
// type.
return FILEPREFIX.TrimEnd('\\') + "\\" + WebServiceType.FullName + ".log";
}
// Receive the file name stored by GetInitializer and store it in a
// member variable for this specific instance.
public override void Initialize(object initializer)
{
filename = (string)initializer;
}
// If the SoapMessageStage is such that the SoapRequest or
// SoapResponse is still in the SOAP format to be sent or received,
// save it out to a file.
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
WriteOutput(message);
break;
case SoapMessageStage.BeforeDeserialize:
WriteInput(message);
break;
case SoapMessageStage.AfterDeserialize:
break;
}
}
public void WriteOutput(SoapMessage message)
{
newStream.Position = 0;
FileStream fs = new FileStream(filename, FileMode.Append,
FileAccess.Write);
StreamWriter w = new StreamWriter(fs);
string soapString = (message is SoapServerMessage) ? "SoapResponse" : "SoapRequest";
w.WriteLine("-----" + soapString + " at " + DateTime.Now);
w.Flush();
Copy(newStream, fs);
w.Close();
newStream.Position = 0;
Copy(newStream, oldStream);
}
public void WriteInput(SoapMessage message)
{
Copy(oldStream, newStream);
FileStream fs = new FileStream(filename, FileMode.Append,
FileAccess.Write);
StreamWriter w = new StreamWriter(fs);
string soapString = (message is SoapServerMessage) ?
"SoapRequest" : "SoapResponse";
w.WriteLine("-----" + soapString +
" at " + DateTime.Now);
w.Flush();
newStream.Position = 0;
Copy(newStream, fs);
w.Close();
newStream.Position = 0;
}
void Copy(Stream from, Stream to)
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}
}
// Create a SoapExtensionAttribute for the SOAP Extension that can be
// applied to an XML Web service method.
[AttributeUsage(AttributeTargets.Method)]
public class TraceExtensionAttribute : SoapExtensionAttribute
{
private string filename = ".\\log.txt";
private int priority;
public override Type ExtensionType
{
get { return typeof(TraceExtension); }
}
public override int Priority
{
get { return priority; }
set { priority = value; }
}
public string Filename
{
get
{
return filename;
}
set
{
filename = value;
}
}
}
2.在web.config中的system.web节点下,加入以下配置
<system.web>
<webServices>
<soapExtensionTypes>
<add type="TraceExtension,App_Code" priority="1" group="0"/>
</soapExtensionTypes>
</webServices>
...
</system.web>
3.启动,访问。就能看到soap报文日志了。
备注及说明:
1.TraceExtension类可以放在你项目中的非App开头的目录下,然后在web.config中App_code修改成dll名字,TraceExtension前加上命名空间即可。但不推荐这么做,因为调试的时候可能会修改TraceExtension的实现,所以最好放在类似App_Code目录下,这样发布的时候,只需要拷贝这个目录及cs文件即可,iis动态编译,修改的时候比较方便
2.附件中的WebService比较简单,但是通过浏览器直接调用的时候,没有记录soap日志,通过类似WebService Studio或新建客户端访问时,能记录日志
3.这个TraceExtension比较简单,直接写文件的方式记录文本日志的,推荐采用NLog或者log4net的方式记录。同时由于这种简单的实现方式,记录日志的目录必须是存在的。我这里的FILEPREFIX就是事先建好的目录~~
附件是完整的项目示例,欢迎交流~~