Home > Microsoft .Net Development Tips > C# Development > More on SOAP extensions
Win Development Tips:
EMAIL THIS
 TIPS & NEWSLETTERS TOPICS 

C# DEVELOPMENT

More on SOAP extensions


Bob Tabor
10.21.2002
Rating: -5.00- (out of 5)


Digg This!    StumbleUpon Toolbar StumbleUpon    Bookmark with Delicious Del.icio.us   


In a previous tip, I explained how SOAP Extensions allow you to plug in and capture/manipulate the SOAP message in ASP.NET as it travels through the ASP.NET Web service chain of events -- from IIS to the ASP.NET ISAPI extension, through the HTTP modules down to the HTTP Handler. I also explained how there are four events (BeforeDeserialize, AfterDeserialize, BeforeSerialize and AfterSerialize) that allow you to inspect or modify the SOAP request message before/after it is deserialized into an object, and before/after the response object is turned back into a SOAP message. Now, I give you the code for the SoapLogger utility. This source code uses some pretty advanced features of .NET, such as the creation of custom attributes, manipulation of memory and file streams, and inheriting and overriding .NET Framework classes and methods (respectively) to implement your own functionality. To use this example, do the following:

  1. Create a new C# class library project called "SoapLogger".
  2. Download the source code and paste it into the Class1.cs file that was provided by Visual Studio.NET when you created the new project. Be sure to remove any existing code from that file before pasting this code into it.
  3. Compile the project. It will create a new assembly in the bin directory of your project called SoapLogger.dll
  4. Open the Web services project you want to add logging to. Open the actual ASMX file (or rather, its code behind file .cs or .vb).
  5. Add a reference to the SoapLogger.dll by right-clicking the project name in the solution explorer and selecting "Add reference..." and the Add Reference dialog will appear.
  6. Find your SoapLogger assembly in the list (or use the browse feature) and create a reference to the component.
  7. Add an attribute to the Web Method you want to log. For example, I used the following code in the method signature to log the results of the UpdateAffiliateDetail Web Method:
    <WebMethod(), SoapLogger()> _
    Public Function UpdateAffiliateDetail(ByVal xdsAffiliate1 _ 
        As dsAffiliate) As Integer
    

    (Notice the underscores in VB.NET!)

    Alternatively, you can send in a location if you don't like the default location and name using a property of the SoapLogger attribute:

    <WebMethod(), SoapLoggerAttribute("d:logslogfile.log")> _
    Public Function UpdateAffiliateDetail(ByVal xdsAffiliate1 _
    As dsAffiliate) As Integer
    
  8. Compile and test your Web service. Once you do, you will see a log file that contains the SOAP messages for each time your Web Method is called.

Here's the C# code:

namespace Logging
{
 using System;
 using System.Collections;
 using System.ComponentModel;
 using System.Data;
 using System.Diagnostics;
 using System.Web;
 using System.Web.Services;
 using System.Web.Services.Protocols;
 using System.IO;
 using System.Xml;

 // Create a new custom attribute that will allow
 // users to configure the log file. This attribute
 // will also tell the ASP.NET system which type to
 // load for our extension
 [AttributeUsage(AttributeTargets.Method)]
 public class SoapLoggerAttribute : SoapExtensionAttribute
 {
  private int _priority = 0;
  private string _logFile = @"C:soap.log";
  public SoapLoggerAttribute() {}
  public SoapLoggerAttribute(string logFile) {_logFile = logFile;}
  public string LogFile {get{return _logFile;}}
  public override Type ExtensionType {get{return typeof(SoapLogger);}}
  public override int Priority {get {return _priority;} set{_priority = value;}}
 }

 // Create a new SoapExtension class. When users
 // apply the above attribute to a method of their 
 // web service, this class will be instantiated
 // by the ASP.NET system
 public class SoapLogger : SoapExtension
 {
  private string LogFile = "";
  private Stream SoapStream;
  private Stream TempStream;

  public override object GetInitializer(Type serviceType)
  {
   // we need to read some service configuration 
// from the attribute so differ creating 
// an initializer
   return null;
  }
  public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
  {
   // whatever we return here will be passed back to
   // our initialize method every time the ASP.NET 
// system needs to create a new instance of 
// this extension class
   return ((SoapLoggerAttribute)attribute).LogFile;
  }
  public override void Initialize(object initializer)
  {
   // grab the logfile name that we returned in
   // GetInitializer
   LogFile = (string)initializer;
  }
  public override Stream ChainStream(Stream stream)
  {
   // by overriding ChainStream we can
   // cause the ASP.NET system to use
   // our stream for buffering SOAP messages
   // rather than the default stream.
   // we will store off the original stream
   // so we can pass the data back down to the 
// ASP.NET system in original stream that 
// it created.
   SoapStream = stream;
   TempStream = new MemoryStream();
   return TempStream;
  }
  public void CopyTextStream(Stream src, Stream dest)
  {
   TextReader reader = new StreamReader(src);
   TextWriter writer = new StreamWriter(dest);
   writer.WriteLine(reader.ReadToEnd());
   writer.Flush();
  }
  public override void ProcessMessage(SoapMessage message)
  {
   // this method will be called several times during
   // the processing of a SOAP request. The 
// ASP.NET system tells us which stage the 
// SOAP request is at with the Stage property 
// of the SoapMessage class
   switch (message.Stage)
   {
    case SoapMessageStage.BeforeDeserialize:
    {
     // copy the SOAP request from the 
// network stream into our memory buffer
     CopyTextStream(SoapStream, TempStream);
     FileStream fs = new FileStream(LogFile, FileMode.Append, FileAccess.Write);
     StreamWriter sw = new StreamWriter(fs);
     sw.WriteLine("** BEGIN SOAP REQUEST: {0}", DateTime.Now);
     sw.Flush();

     // copy the mem buffer stream to the 
// log file
     TempStream.Position = 0;
     CopyTextStream(TempStream, fs);
     sw.WriteLine("** END SOAP REQUEST");
     sw.Flush();
     fs.Close();

     // reset the memory buffer position
     // so the ASP.NET system can parse and
     // decode the message
     TempStream.Position = 0;
    }
     break;
    case SoapMessageStage.AfterSerialize:
    {
     FileStream fs = new FileStream(LogFile, FileMode.Append, FileAccess.Write);
     StreamWriter sw = new StreamWriter(fs);
     sw.WriteLine("** BEGIN SOAP RESPONSE: {0}", DateTime.Now);
     sw.Flush();
     TempStream.Position = 0;
     CopyTextStream(TempStream, fs);
     sw.WriteLine("** END SOAP RESPONSE");
     sw.Flush();

     // copy the memory buffered response 
     // to the network stream
     TempStream.Position = 0;
     CopyTextStream(TempStream, SoapStream);

     fs.Close();
    }
     break;
   }

   return;
  }
 }
}

Notice that the SoapLogger class derives from the SoapExtension class. This is how you "plug into" the architecture of the HTTP Handler for Web services. Then, you must override several methods, such as Initialize, GetInitializer (allows you to retrieve the properties of the attribute, or set default values), ChainStream (allows you to copy off the memory stream for processing) and most importantly the ProcessMessage method, that allows you to determine which stage the SOAP request/response is currently in. If you take a look in the example above in the ProcessMessage method, I only test for two SoapMessageStages -- BeforeDeserialize and AfterSerialize. Why is that? Because this is when the message is actually a SOAP message, and is not in its object form.

You can extend this sample and build all sorts of inspection and logging into your Web service applications. This should give you plenty of meat to cut your teeth on. Until next time...


About the Author

Robert Tabor is a Microsoft Certified Professional in Visual Basic with over six years of experience developing n-tier Microsoft-centric applications for some of the world's most prestigious companies and consulting organizations, such as Ernst & Young, KPMG, Cambridge Technology Partners, Sprint, American Heart Association, and the Mary Kay Corporation. Bob is the author of Microsoft .NET XML Web services by Sams Publishing, and contributes to SoapWebservices.com and LearnVisualStudio.NET. He is currently working on initiatives within Mary Kay, the second largest eCommerce site in retail volume on the net, of how to utilize .NET within their e-business group.

Rate this Tip
To rate tips, you must be a member of SearchWinDevelopment.com.
Register now to start rating these tips. Log in if you are already a member.




Digg This!    StumbleUpon Toolbar StumbleUpon    Bookmark with Delicious Del.icio.us   



RELATED CONTENT
C# Development
Let Microsoft StyleCop tame your wild C#
Picking a .NET smart client communications technology
LINQ beyond queries: Strong-typed refection
Book excerpt: An introduction to DSL tools
Assembly versioning in the .NET Framework 2.0
Book excerpt: Creating graphical output using the .NET Compact Framework
On Extension Methods in C# and .NET Framework 3.5
Generate RSA public and private keys, export to XML
Book excerpt: Upgrading to Visual Studio 2005
Learning .NET: Tips for getting started with .NET development

ASP.NET Development
How to use jQuery to solve Javascript browser compatibility problems
How to write an out-of-browser Silverlight 3 application in 3 steps
Silverlight 3 beta SDK download lets developers try new RIA features
Visual Studio's IntelliSense for jQuery doesn't autocomplete correctly
Dundas Map for .NET kicks up geographic visualization
Return to CodePlex: Into the Sandcastle…
VBScript Tutorial
Use PHP with Visual Studio to create Web sites
Visual Studio Team System Add-ins: Conchango Scrum for Team System and Scrum Dashboard
Visual Studio 2008 and .NET Framework 3.5 SP1 introduces ADO .NET Entity Designer

C# programming language
Inside Visual Studio 2010
Mono 2.0 moves .NET apps to Linux - includes migration analyzer
LINQ beyond queries: Strong-typed refection
Assembly versioning in the .NET Framework 2.0
Book excerpt: Creating graphical output using the .NET Compact Framework
Visual Studio 2008 Learning Guide: C# 3.0
Simonyi firm to address divide between domain experts and developers
On Extension Methods in C# and .NET Framework 3.5
Generate RSA public and private keys, export to XML
Book excerpt: Upgrading to Visual Studio 2005

RELATED GLOSSARY TERMS
Terms from Whatis.com − the technology online dictionary
C#  (SearchWinDevelopment.com)
GLib  (SearchWinDevelopment.com)

RELATED RESOURCES
2020software.com, trial software downloads for accounting software, ERP software, CRM software and business software systems
Search Bitpipe.com for the latest white papers and business webcasts
Whatis.com, the online computer dictionary

DISCLAIMER: Our Tips Exchange is a forum for you to share technical advice and expertise with your peers and to learn from other enterprise IT professionals. TechTarget provides the infrastructure to facilitate this sharing of information. However, we cannot guarantee the accuracy or validity of the material submitted. You agree that your use of the Ask The Expert services and your reliance on any questions, answers, information or other materials received through this Web site is at your own risk.



Database Programming Solutions - .NET XML, Visual Studio LINQ, ORM .NET
About Us  |  Contact Us  |  For Advertisers  |  For Business Partners  |  Site Index  |  RSS
SEARCH 
TechTarget provides technology professionals with the information they need to perform their jobs - from developing strategy, to making cost-effective purchase decisions and managing their organizations' technology projects - with its network of technology-specific websites, events and online magazines.

TechTarget Corporate Web Site  |  Media Kits  |  Site Map




All Rights Reserved, Copyright 2000 - 2009, TechTarget | Read our Privacy Policy
  TechTarget - The IT Media ROI Experts