DekGenius.com
[ Team LiB ] Previous Section Next Section

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.

    [ Team LiB ] Previous Section Next Section