Walkthrough: Altering the SOAP Message Using SOAP Extensions

This topic is specific to a legacy technology. XML Web services and XML Web service clients should now be created using Windows Communication Foundation.

SOAP extensions can be inserted into the .NET Framework SOAP message processing pipeline to modify or inspect a SOAP request or response message while it is being serialized or deserialized, on either the Web service or client. This step-by-step topic shows how to build and run a SOAP extension. For a picture of how SOAP extensions work, as well as the order in which SOAP extension methods are called in the message processing pipeline, see SOAP Message Modification Using SOAP Extensions.

During this walkthrough, you learn how to:

  • Derive a class from SoapExtension.

  • Save references to the Stream objects that represent future SOAP messages before and after the SOAP extension has done its processing.

  • Initialize SOAP extension specific data.

  • Process the SOAP messages during the applicable SoapMessageStage or stages.

Configure the SOAP extension to run with specific Web service methods.

Prerequisites

Derive a Class from SoapExtension.

The class that derives from SoapExtension is the class that performs the functionality of the SOAP extension. That is, if the SOAP extension is an encryption SOAP extension, then the class that derives from the SoapExtension class performs the encryption and corresponding decryption.

Save References to Stream Objects Representing Future SOAP Messages

To modify a SOAP message, you need to obtain a reference to the stream that can be used to obtain the contents of future SOAP messages. Your only opportunity to obtain this reference is to override the ChainStream method.

To save references to Stream objects representing future SOAP messages

  1. Override the ChainStream method.

    The ChainStream method has the following signature:

    public virtual Stream ChainStream(Stream stream)
    
    Public Overridable Function ChainStream(ByVal stream As Stream) As Stream
    
  2. Within the ChainStream implementation, assign the Stream instance passed as a parameter.

    A reference to a Stream is passed into the ChainStream once, prior to any SoapMessageStage. This Stream refers to the XML of the SOAP message after SOAP extensions of lower priority (see Configure the SOAP Extension to Run with Web Service Methods for details about SOAP extension priorities) have executed and made their changes to the SOAP message. A SOAP extension should assign this reference to a member variable for later access during the SoapMessageStage , when a SOAP extension inspects or modifies the SOAP message.

    The Stream passed into ChainStream, however, is not the Stream a SOAP extension should modify.

  3. Within the ChainStream implementation, instantiate a new Stream, save a reference to it in a private member variable, and return the reference.

    The following example demonstrates a common implementation of the ChainStream method.

For an example of a common implementation of the ChainStream method, see How to: Implement the ChainStream Method to Save References to Stream Objects.

Initialize SOAP Extension Specific Data

The class that derives from SoapExtension has two methods for initializing data, GetInitializer and Initialize.

At what time the ASP.NET infrastructure calls the GetInitializer method, and what parameters are passed to the method, depend on how the SOAP extension is configured. (See SOAP Message Modification Using SOAP Extensions and Configure the SOAP Extension to Run with Web Service Methods.

To initialize data when the SOAP extension is configured using an attribute

  1. Implement the GetInitializer method using the following signature:

    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
    
    Public Overloads Overrides Function GetInitializer(methodInfo As _
       LogicalMethodInfo, attribute As SoapExtensionAttribute) As Object
    

    The LogicalMethodInfo provides prototype details about the Web service method, such as the number of parameters and their data types.

  2. If necessary, call the Initialize method, passing the object returned by GetInitializer. For many SoapExtension implementations, the Initialize method can be left empty.

To initialize data when the SOAP extension is configured in a configuration file

  1. Implement the GetInitializer method with the following signature:

    public override object GetInitializer(Type WebServiceType)
    
    Public Overloads Overrides Function GetInitializer(WebServiceType As Type) As Object
    

    The Type parameter is the type of the class of the class that implements the Web service.

  2. If necessary, call the Initialize method, passing the object returned by GetInitializer. For many SoapExtension implementations, the Initialize method can be left empty.

For an example of how to initialize cached data when a SOAP extension is configured see, How to: Initialize Cached Data When a SOAP Extension is Configured.

Process the SOAP Messages

In the class derived from SoapExtension, the core piece of implementation is the ProcessMessage method. This method is called several times by ASP.NET at each of the stages defined in the SoapMessageStage enumeration.

To process SOAP messages

  • Implement the abstract ProcessMessage method.

    The following implementation of the ProcessMessage method traces a call to a Web service. During the trace, if the SoapMessageStage indicates the parameters have been serialized into XML, the XML is written to a file.

    public override void ProcessMessage(SoapMessage message) 
    {
       switch (message.Stage) 
       {
       case SoapMessageStage.BeforeSerialize:
           break;
       case SoapMessageStage.AfterSerialize:
           // Write the SOAP message out to a file.
           WriteOutput( message );
           break;
       case SoapMessageStage.BeforeDeserialize:
           // Write the SOAP message out to a file.
           WriteInput( message );
           break;
       case SoapMessageStage.AfterDeserialize:
           break;
       default:
           throw new Exception("invalid stage");
       }
    }
    
    Public Overrides Sub ProcessMessage(message As SoapMessage)
        Select Case message.Stage
          Case SoapMessageStage.BeforeSerialize
          Case SoapMessageStage.AfterSerialize
            ' Write the SOAP message out to a file.
            WriteOutput(message)
          Case SoapMessageStage.BeforeDeserialize
            ' Write the SOAP messae out to a file.
            WriteInput(message)
          Case SoapMessageStage.AfterDeserialize
          Case Else
            Throw New Exception("invalid stage")
        End Select
    End Sub
    

Configure the SOAP Extension to Run with Web Service Methods

A SOAP extension can be configured to run using a custom attribute or by modifying a configuration file. A custom attribute is applied to a Web service method. When a configuration file is used, the SOAP extension runs with all Web services within the scope of the configuration file. For details on how configuration files work, see Configuring Applications.

To configure a SOAP extension using a custom attribute

  1. Derive a class from SoapExtensionAttribute.

  2. Implement two properties of SoapExtensionAttribute: ExtensionType and Priority. A SOAP extension should return the type of the SOAP extension in the ExtensionType property. The Priority property represents the relative priority of the SOAP extension, as explained in Applying the Priority Group in SOAP Message Modification Using SOAP Extensions.

  3. Apply the custom attribute to each Web service method you want the SOAP extension to run with.

To configure a SOAP extension in a configuration file

  1. If it is not already present, add a soapExtensionTypes XML element to the webServices section of the appropriate App.config or Web.config file.

  2. Within the soapExtensionTypes XML element, add an add XML element for each SOAP extension you want to run with every Web service within the scope of the configuration file.

    The add XML element has the following properties.

    • type: specifies the type of the SOAP extension and the assembly it resides in.

    • priority: Specifies the relative priority of the SOAP extension within its group.

    • Group: specifies the group a SOAP extension is a member of.

See Also

Tasks

How to: Implement a SOAP Extension
How to: Initialize Cached Data When a SOAP Extension is Configured
How to: Implement the ChainStream Method to Save References to Stream Objects

Reference

SoapExtension
SoapExtensionAttribute
SoapMessageStage
LogicalMethodInfo

Concepts

SOAP Message Modification Using SOAP Extensions
Anatomy of an XML Web Service Lifetime
Building XML Web Service Clients

Other Resources

Configuring Applications