6.6 SOAP Header in Web Services
As you have seen from the web service consumer using SOAP, the data
being passed back and forth as is structured XML inside the body of
the HTTP package. In particular it has the following format:<Envelope>
<Header>
< . . . >
</Header>
<Body>
< . . . >
</Body>
</Envelope>
We have seen how to pass data from the client to the web service
through the Body of the Envelope. In this section, we show how to use
the Header of the Envelope.Through this optional header node, the developers can pass
information that does not relate to any particular web method or
information that is common to all web methods. Of course, you can
pass information that does not related to any particular web method
in a method call itself, such as
InitiateService(param) enforcing a usage rule that
this method has to be called first. This is not an elegant solution.
Just add the param of the InitiateService to the
header. On the other hand, if all web methods of your service require
a common parameter, wouldn't it be nice if you could
just set up the header and didn't have to worry
about this parameter for each of the web methods. Examples of header
information are a security token, a payment token, priority, and so
on; there is no reason to pass these pieces of common information via
every web method.Once you construct your web service to use a SOAP header, the WSDL
will instruct the client that a header node is in place so that a web
service client knows how to set up the header information before
making a call to the web service methods. The following example
should provide some clarification:<%@ WebService Language="C#" Class="TestHeader.PayWS" %>
namespace TestHeader {
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
public class Payment : SoapHeader {
public string CreditCardNumber;
}
[WebService(Namespace="http://Oreilly/DotNetEssentials/")]
public class PayWS : WebService {
public Payment clientPayment;
[WebMethod, SoapHeader("clientPayment")]
public string Task1( ) {
return string.Format("Task1 performed. " +
"Charging $25,000.00 on credit card: {0}",
clientPayment.CreditCardNumber);
}
[WebMethod, SoapHeader("clientPayment")]
public string Task2( ) {
return string.Format("Task2 performed. " +
"Charging $4,500.00 on credit card: {0}",
clientPayment.CreditCardNumber);
}
}
}
In this example, we create a web service with two methods, Task1 and
Task2. Both of these methods use the Payment object in the soap
header.The SOAP request and response format for Task1 follows:POST /SOAPHeader/PayWS.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://Oreilly/DotNetEssentials/Task1"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<Payment xmlns="http://Oreilly/DotNetEssentials/">
<CreditCardNumber>string</CreditCardNumber>
</Payment>
</soap:Header>
<soap:Body>
<Task1 xmlns="http://Oreilly/DotNetEssentials/" />
</soap:Body>
</soap:Envelope>
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Task1Response xmlns="http://Oreilly/DotNetEssentials/">
<Task1Result>string</Task1Result>
</Task1Response>
</soap:Body>
</soap:Envelope>
This is different than the soap envelope we've seen
for PubsWS where there was no SOAP header. In this case, the header
is an object of type Payment and this Payment class has a string
property called CreditCardNumber.Our example expects the clients to this web service to pass in the
Payment object. The following is the client code. Of course, you will
have to generate the proxy class for the PayWS web service using
wsdl.exe and compile this proxy along with the
client code:public class ClientWS {
public static void Main( ) {
// Create a proxy
PayWS oProxy = new PayWS( );
// Create the payment header.
Payment pmt = new Payment( );
pmt.CreditCardNumber = "1234567890123456";
// Attach the payment header to the proxy.
oProxy.PaymentValue = pmt;
// Call Task1.
System.Console.WriteLine(oProxy.Task1( ));
// Call Task2.
System.Console.WriteLine(oProxy.Task2( ));
}
}
The output of the client:Task1 performed. Charging $25,000.00 on credit card: 1234567890123456
Task2 performed. Charging $4,500.00 on credit card: 1234567890123456
The above is a trivial usage of SOAP header. In reality, the SOAP
headers are probably not as simple as our Payment class.Microsoft, IBM, and a number of other companies have been working on
the Global XML web services Architecture (GXA) that defines a
framework on how to build standardized web services incorporating
security, reliability, referral, routing, transaction, and so on. A
number of GXA specifications use SOAP Header as the means for this
infrastructure.