Wrox Home  
Professional ASP.NET 2.0 XML
by Thiru Thangarathinam
January 2006, Paperback

Excerpt from Professional ASP.NET 2.0 XML

Using SOAP Headers with ASP.NET 2.0 Web Services

by Thiru Thangarathinam

When you communicate with a Web service using SOAP, the SOAP message that is sent to the Web service follows a standard format. The XML document inside the SOAP message is structured into two main parts: the optional headers and the mandatory body. The Body element comprises the data specific to the message. The optional Header element can contain additional information not directly related to the particular message. Each child element of the Header element is called a SOAP header.

SOAP headers are also a good place to put optional information, and a good means to supporting evolving interfaces. For example, imagine your bank allows you to manage multiple accounts with one ATM card. If you use your bank's ATM, you now have to specify if you want the withdrawal to be made from my primary, secondary, or tertiary account. If you use an ATM from another bank that isn't affiliated with you bank, you do not get asked that question. So the account identifier is clearly an optional parameter, with a reasonable default.

ASP.NET provides a mechanism for defining and processing SOAP headers. You can define a new SOAP header by deriving from the SoapHeader class. After you define a SOAP header, you can then associate the header with a particular endpoint within the Web service by using the SoapHeader attribute. Table 1 lists the properties exposed by the SoapHeader class.

Table 1. Properties of the SoapHeader Class
Property Description
Actor Indicates the intended recipient of the header.
DidUnderstand Indicates whether a header whose mustUnderstand attribute is true was understood and processed by the recipient.
EncodedMustUnderstand Indicates whether a header whose mustUnderstand attribute is true and whose value is encoded was understood and processed by the recipient. This property is used when communicating with the SOAP 1.1 version.
EncodedMustUnderstand12 Very similar to EncodedMustUnderstand except that it is used in conjunction with SOAP 1.2 version.
MustUnderstand Indicates whether the header must be understood and processed by the recipient.
Relay Indicates if the SOAP header is to be relayed to the next SOAP node if the current node does not understand the header.
Role Indicates the recipient of the SOAP header.

By default, the name of the class derived from SoapHeader will become the name of the root header element, and any public fields or properties exposed by the class will define elements within the header. SOAP headers are defined by classes derived from the SoapHeader class. Elements within the header are defined by public fields or read/writable properties.

Implementing a SOAP Header Class

Imagine you want to modify the QuotesService used in the previous examples to accept a SOAP header that contains the payment information. Listing 1 illustrates the definition of the Payment header.

Listing 1: SOAP Header Declaration
using System;
using System.Xml;
using System.Xml.Serialization;
using System.Web.Services.Protocols;
public class SoapPaymentHeader : SoapHeader
  private string nameOnCard;
  private string creditCardNumber;
  private CardType creditCardType;
  private DateTime expirationDate;	
  public string NameOnCard
    get { return nameOnCard; }
    set { nameOnCard = value; }
  public string CreditCardNumber
    get { return creditCardNumber; }
    set { creditCardNumber = value; }
  public CardType CreditCardType
    get { return creditCardType; }
    set { creditCardType = value; }
  public DateTime ExpirationDate
    get { return expirationDate; }
    set { expirationDate = value; }

The preceding class definition defines a SOAP header named SoapPaymentHeader with four child elements: NameOnCard, CreditCardNumber, CreditCardType, and ExpirationDate.

This code uses an enum named CardType that is declared as follows:

public enum CardType

After you define the headers, the next step is to associate them with the actual Web service method.