SOAP Extensions

only for RuBoard

Using ASP.NET SOAP extensions, you can inspect or alter a SOAP message in an XML Web Service at specific stages in message processing on either the client or the server. Altering messages gives you a chance to implement a layer for encryption or compression of messages on top of an existing XML Web Service. Inspecting the messages is useful to debug your web services.

ASP.NET SOAP extensions derive from the SoapExtension class. Overriding the ProcessMessage method in the SoapExtension base class gives you an opportunity to read or change the messages because this method can be called at each of the four stages defined in SoapMessageStage enum. (Note that the inline comments in Listing 11.7 explain these four stages.)

Using SOAP Extensions to Trace SOAP Messages

The .NET Framework does not provide a direct tool to trace SOAP messages, which is a useful aspect for a web service and the web service client developers. You can build a tracing mechanism to log the SOAP messages using the SOAP extensions. Listing 11.7 shows a sample web service that exposes a single method, GetAddressEntry() , and uses SOAP extension to log the SOAP request and response messages to a file.

Listing 11.7 Tracing SOAP Messages Using SOAP Extensions ( service1.asmx )
 <%@ WebService Language="c#" Class="TracingAddressEntries" %>  using System;  using System.IO;  using System.Web.Services;  using System.Web.Services.Protocols;  public class TracingAddressEntries : WebService       {           [WebMethod]            //set a file name to log messages using the trace extension            //attribute            [TraceExtension(Filename="C:\log.txt" )]           public AddressEntry GetAddressEntry()           {                AddressEntry addrEntry = new AddressEntry();                 addrEntry.EntryId = 1000;                 addrEntry.FirstName = "Maria";                 addrEntry.LastName = "Anders";                 addrEntry.Email = "maria@alfreds-futterkiste.com" ;                 addrEntry.Phone = "030-0074321";                 return addrEntry;           }       }  public class AddressEntry  {      public int EntryId;       public string FirstName ;       public string LastName ;       public string Email ;       public string Phone ;  }  //trace extension attribute class inheriting from the SoapExtensionAttribute  [AttributeUsage(AttributeTargets.Method)]  public class TraceExtensionAttribute : SoapExtensionAttribute {     private string filename = "c:\trace.txt";//default filename      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;          }      }  }  public class TraceExtension : SoapExtension {     Stream oldStream;      Stream newStream;      string filename;  // When the SOAP extension is accessed for the first time, the filename  //passed in using the corresponding SoapExtensionAttribute is stored.      public override object GetInitializer(LogicalMethodInfo methodInfo, graphics/ccc.gif SoapExtensionAttribute attribute) {         return ((TraceExtensionAttribute) attribute).Filename;      }       public override object GetInitializer(Type serviceType){           return typeof(TraceExtension);       }  // Receive the filename stored by GetInitializer and store it in a member  //variable for this specific instance.       public override void Initialize(object initializer) {           filename = (string) initializer;       }  //overriding the ProcessMessage method. This method gives us a chance to  //alter the SOAP Messages before sending the SAOP messages to the network  //and soon after a SOAP message is available from a client.      public override void ProcessMessage(SoapMessage message) {         switch (message.Stage) {         case SoapMessageStage.BeforeSerialize:  //The stage just prior to a SoapMessage being serialized. There is no XML  //Response yet so do nothing.              break;          case SoapMessageStage.AfterSerialize:  //The stage just after a SoapMessage is serialized, but before the SOAP  //message is sent over the wire. The XML SOAP Response is available. Capture  //it in a file.              WriteOutput( message );              break;          case SoapMessageStage.BeforeDeserialize:  //The stage just before a SoapMessage is deserialized from the SOAP message  //sent across the network into a .NET object. The request from the client  //is available as XML. Capture it in a file.              WriteInput( message );              break;          case SoapMessageStage.AfterDeserialize:  //The stage just after a SoapMessage is deserialized from a SOAP message into  //an object.              break;          default:              throw new Exception("invalid stage");          }      }  // 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;      }  //capturing the XML SOAP Response to the log file      public void WriteOutput( SoapMessage message ){         newStream.Position = 0;              FileStream fs = new FileStream(filename, FileMode.Append, FileAccess.Write);          StreamWriter w = new StreamWriter(fs);          w.WriteLine("---------------------------------- Response at " + DateTime.Now);          w.Flush();          Copy(newStream, fs);          fs.Close();          newStream.Position = 0;          Copy(newStream, oldStream);      }  //capturing the XML SOAP Request to the log file      public void WriteInput( SoapMessage message ){         Copy(oldStream, newStream);              FileStream fs = new FileStream(filename, FileMode.Append, graphics/ccc.gif <%FileAccess.Write);          StreamWriter w = new StreamWriter(fs);          w.WriteLine("================================== Request at " + DateTime.Now);          w.Flush();          newStream.Position = 0;          Copy(newStream, fs);          fs.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();      }  } 

Although in Listing 11.7 the two classes TraceExtensionAttribute and TraceExtension are placed in the same asmx file, you can place them in a different .cs file and convert the file into an assembly so that you can use it for all other web services on the web server.

The following is the SOAP request and response captured in the log.txt file:

 ================================== Request at 10/30/2001 6:05:07 AM  <?xml version="1.0" encoding="utf-8"?><soap:Envelope  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetAddressEntry  xmlns="http://tempuri.org/" /></soap:Body></soap:Envelope>  ---------------------------------- Response at 10/30/2001 6:05:07 AM  <?xml version="1.0" encoding="utf-8"?><soap:Envelope  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetAddressEntryResponse  xmlns="http://tempuri.org/"><GetAddressEntryResult><EntryId>1000</EntryId> graphics/ccc.gif <FirstName>Maria</FirstName><LastName>Anders</LastName><Email>maria@alfreds graphics/ccc.gif futterkiste.com</Email><Phone>030-0074321</Phone></GetAddressEntryResult> </ graphics/ccc.gif GetAddressEntryResponse></soap:Body></soap:Envelope> 

To implement a custom encryption of messages, you must replace the WriteOutput() used in Listing 11.7 by a method (for example, Encrypt() ) that encrypts the SOAP response before sending it over the wire and the WriteInput() method by a method (for example, Decrypt() ) that decrypts an encrypted SOAP request that's sent by the client. These methods should not tamper with the entire SOAP messages, but only the contents inside the body of the SOAP messages. Tampering with the other structures makes them invalid SOAP messages for the underlying SOAP implementations .

only for RuBoard


XML and ASP. NET
XML and ASP.NET
ISBN: B000H2MXOM
EAN: N/A
Year: 2005
Pages: 184

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net