2010年3月15日 星期一

How can I log my .NET SOAP requests

Env: Visual Studio 2005

If you make direct SOAP requests, you need to use SOAP extension to log your requests and responses. SOAP extensions is a Microsoft ASP.NET WebMethod interception mechanism that can be used to manipulate SOAP requests/responses before they are sent on the wire.

Here are the steps to implement a SOAP Extension:

1. Using Visual Studio .NET, create a new .NET class library project in the language of your choice and add the SOAP extension.
2. Add the SOAP extension assembly as reference and declare the SOAP extension on the XML Web service reference of our application

Here is a C# sample adapted from the SOAP Extension sample code at Microsoft MSDN

using
System;
using
System.Web.Services;
using
System.Web.Services.Protocols;
using
System.IO;

namespace TraceExtension
{

public class TraceExtension : SoapExtension
{
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;
}

public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
return null
;
}

public override object GetInitializer(Type WebServiceType)
{
return null
;
}

public override void Initialize(object initializer)
{
// Set the log file
filename= "c:\\log.txt";
}

// SaveSoapRequest or SoapResponse to the log 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
;
default
:
throw
new Exception("invalidstage");
}
}

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 SoapExtensionAttributefor the SOAP Extension that can be applied to an XML Web service method.
[AttributeUsage(AttributeTargets.Method)]
public
class TraceExtensionAttribute : SoapExtensionAttribute
{
private
int priority;

public
override Type ExtensionType
{
get
{ return typeof(TraceExtension); }
}

public override int Priority
{
get
{ return priority; }
set
{priority = value; }
}
}

}

Save this library project as TraceExtension and compile.


In the project where you invoke your Web Services:

  • In the Solution Explorer, Click on "Show All Files"
  • Expand Web References and double click on References.cs
  • Locate the method for which you wish to add logging.
  • Declare the SOAP Extension as follows:

[System.Web.Services.Protocols.SoapDocumentMethodAttribute("",Use=System.Web.Services.Description.SoapBindingUse.Literal,ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare),TraceExtension.TraceExtension()]

Here is how to add it to GeteBayOfficialTime:

[System.Web.Services.Protocols.SoapHeaderAttribute("RequesterCredentials",Direction=System.Web.Services.Protocols.SoapHeaderDirection.InOut)]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("",Use=System.Web.Services.Description.SoapBindingUse.Literal,ParameterStyle=System.Web.Services.Protocols.Soap arameterStyle.Bare),TraceExtension.TraceExtension()]
[return:System.Xml.Serialization.XmlElementAttribute("GeteBayOfficialTimeResponse",Namespace="urn:ebay:apis:eBLBaseComponents")]
public
GeteBayOfficialTimeResponseTypeGeteBayOfficialTime ([System.Xml.Serialization.XmlElementAttribute(Namespace="urn:ebay:apis:eBLBaseComponents")]GeteBayOfficialTimeRequestType GeteBayOfficialTimeRequest)
{
object
[] results = this.Invoke("GeteBayOfficialTime",new object[] {
GeteBayOfficialTimeRequest});
return
((GeteBayOfficialTimeResponseType)(results[0]));
}



source: http://ebay.custhelp.com/cgi-bin/ebay.cfg/php/enduser/std_adp.php?p_faqid=350

沒有留言: