c#2.0使用TraceExtension记录WebService的Soap日志

在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就是事先建好的目录~~

附件是完整的项目示例,欢迎交流~~

你可能感兴趣的:(webservice,C#,soap报文)