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 { VISA, MASTERCARD, AMX, DISCOVER }
After you define the headers, the next step is to associate them with the actual Web service method.