Now legacy languages such as VB6 and Perl,[9] and .NET languages, such as C# and VB.NET, to demonstrate the cross-language/cross-platform benefits of web services.
[9] We use SOAP::Lite PERL modules. See  ( it will give you a list of supported methods. To find out more about these methods, click one of them. This brings up a default web service consumer. This consumer, autogenerated through the use of reflection, is great for testing your web services' methods.[10] It uses the HTTP GET protocol to communicate with the web service. This consumer features a form that lets you test the method (see Figure 6-3), as well as descriptions of how to access the method via SOAP, HTTP GET, or HTTP POST.
[10] A simple reflection example can be found in Section 4.3.1.3. < <xs:element <xs:complexType> <xs:sequence> <xs:element <xs:element <xs:element <xs:element <xs:element <xs:element <xs:element <xs:element <xs:element <SelectedAuthor diffgr: > </SelectedAuthor> </NewDataSet> </diffgr:diffgram> </DataSet>
In the section "HTTP GET Consumer," we saw the automatic creation of a web services consumer by merely hitting the URL of the web services, :[11]
[11] wsdl.exe generates the proxy source code similar to the way IDL compilers generate source files for DCOM proxies. The only difference is that WSDL is the language that describes the interface of the software component, which is XML-based.
wsdl /l:CS /protocol:HttpPost 
This command line creates a proxy for the PubsWS web service from the WSDL document from the URL  The proxy uses HTTP POST as its protocol to talk to the web service; it is generated as a C# source file. The wsdl tool or /protocol:SOAP2[12] parameters, the PubsWS derives from either the HttpGetClientProtocol or SoapHttpClientProtocol class.
[12] In .NET Framework 1.1, SOAP 1.2 is also supported via /protocol:SOAP12. All this does is generate the SOAP derived proxy for SOAP Version 1.2..[13] To make use of the proxy, you also have to add to your project any references that the proxy depends on. In this example, the necessary references for the proxy file are System.Web.Services, System.Web.Services.Protocols, System.Xml.Serialization, and System.Data.
[13] For other languages, use wsdl with the /l option to specify the language. See Appendix D for more details. Authors toAuthors( )Authors( ) to generate.[14]
[14] You can find the proxy source file under Web References\ReferenceName as reference.cs (if you're working with C#). If you have not renamed the reference name, it is localhost by default. (You might have to select the option to "show all files" in VS.NET Solution Explorer.) data type is used by the HTTP POST call --> <s:element <s:complexType> <s:sequence> <s:element </s:sequence> </s:complexType> </s:element> <!-- This data type is used by the HTTP POST call --> <s:element <s:complexType> <s:sequence> <s:element <s:complexType> <s:sequence> <s:element <s:any /> </s:sequence> </s:complexType> </s:element> </s:sequence> </s:complexType> </s:element> <!-- This data type is used by the SOAP call --> <s:element <s:complexType> <s:sequence> <s:element </s:sequence> </s:complexType> </s:element> <!-- This data type is used by the SOAP call --> <s:element <s:complexType> <s:sequence> <s:element <s:complexType> <s:sequence> <s:element <s:any /> </s:sequence> </s:complexType> </s:element> </s:sequence> </s:complexType> </s:element> <!-- This data type is used by the HTTP GET call --> <s:element <s:complexType /> </s:element> <!-- This data type is used by the HTTP GET call --> <s:element <s:complexType> <s:sequence> <s:element <s:complexType> <s:sequence> <s:element <s:any /> </s:sequence> </s:complexType> </s:element> </s:sequence> </s:complexType> </s:element> <!-- This data type is used by the HTTP GET/POST responses --> <s:element <s:any /> </s:sequence> </s:complexType> </s:element> </types> <!-- These messages are used by the SOAP call --> <message name="GetBooksByAuthorSoapIn"> <part name="parameters" element="s0:GetBooksByAuthor" /> </message> <message name="GetBooksByAuthorSoapOut"> <part name="parameters" element="s0:GetBooksByAuthorResponse" /> </message> <!-- These messages are used by the HTTP GET call --> <message name="GetBooksHttpGetIn" /> <message name="GetBooksHttpGetOut"> <part name="Body" element="s0:DataSet" /> </message> <!-- These messages are used by the HTTP POST call --> <message name="GetAuthorHttpPostIn"> <part name="sSSN" type="s:string" /> </message> <message name="GetAuthorHttpPostOut"> <part name="Body" element="s0:DataSet" /> </message> <!--"> < <operation name="GetBooks"> < <input> < /> </input> <output> <mime:mimeXml </output> </operation> </binding> <!-- HTTP POST binding --> <binding name="PubsWSHttpPost" type="s0:PubsWSHttpPost"> < <operation name="GetAuthor"> < <input> <mime:content </input> <output> <mime:mimeXml </output> </operation> </binding> <!-- The whole web service and address bindings --> <service name="PubsWS"> <port name="PubsWSSoap" binding="s0:PubsWSSoap"> <soap:address < < location=" /> </port> </service> < and POST, as well as the names cmdGet and cmdPost, respectively. After that, drag the WebBrowser object from the toolbar onto the form, and name the control myWebBrowser. If you make the WebBrowser navigate to about:blank initially, method is set to false. After the method invocation is done, we transform the XML result using templateTitle.xsl and display the HTML on the myWebBrowser instancein this case, method GetAuthor. Because this is a POST request, we have to specify in the HTTP header that the request is coming over as a form by setting the Content-Type header header:xsl="  filespecifically, the SOAP sectionwe can use XMLHTTP again to communicate in SOAP dialog. Let's see how this can be done.
Let's go back to the example of consumer web services using VB6 and XMLHTTP. Add another button on the form, and call it cmdSOAP with-Type to text/xml instead of application/x-www-form-urlencoded as for the HTTP POST. By this time, it should be clear to you that only HTTP POST and SOAP care about the Content-Type because they send the data in the body of the HTTP request. The HTTP GET protocol does not really care about the Content-Type because all of the parameters are packaged into the query string. In addition to the difference in format of the data content, you also have to refer to the WSDL to set the SOAPAction header variable to the call you want. Looking back at the SOAP section of the WSDL, if you want to call the GetBooks(sAuthorSSN) method of the web service, you will set the SOAPAction header variable to  On the other hand, if you want to call the GetBooks( ) method instead, the SOAPAction variable has to be set to  The reason the namespace is  inside an Envelope. With the previously specified request, the response SOAP message looks like this:
<?xml version="1.0"?> <soap:Envelope . . . namespace omitted . . . > <soap:Body> <GetBooksByAuthorResult xmlns=" <result> <xsd:schema : <xsl:value-of (<xsl:value-of, <xsl:value-of) </I> <>
It's ok to go through the previous exercise to understand how to write a VB application as a front-end client for web services. However, for your real-life applications, you should use a SOAP toolkit (such as the Microsoft SOAP toolkit) to make things easier.
The next couple of examples take a step further. This time, we will use Perl to access our sample web service PubWS with the help of ActiveState Perl and SOAP::Lite Perl Library (author: Paul Kulchenko).[15]
[15]  and  respectively.
With SOAP::Lite Perl Library, all you have to do is to create a SOAP::Lite object (similar to the proxy object in the C# example) and setup its uri and proxy properties. Once this is done, you can ask the proxy object to run the remote web methods. The uri property maps to the first part of the soapAction and the web method name maps to the second part. The proxy property maps to the physical location of the web service itself.
In our first Perl example, we want to call the GetAuthors web method. This method does not take any parameter and returns a DataSet object. The SOAP portion of the WSDL states that the soapAction for this method is  By default, SOAP::Lite library constructs the soapAction as <uri string> + "#" + <web method name>. This does not agree with web services written on the .NET Framework, where the soapAction is uri_string + "/" + web method name. Fortunately, the SOAP::Lite library provides a callback-like kind of feature so that we can plug in a sub-routine to override the default construction of the soapAction string. The highlighted line of PERL script below basically just concatenates the uri string and the web method name. For simplicity, we rely on the fact that the uri string already has the trailing slash.[16]
[16] The trace for the SOAP::Lite library turns out to be extremely useful because it shows the SOAP request and response as well as other vital information. Insert trace => all at the end of the first line of the example.
To run the program, just type perl <program name>:
use SOAP::Lite on_action => sub {sprintf '%s%s', @_}; my $proxy = SOAP::Lite -> uri(' -> proxy(' my $method = SOAP::Data->name('GetAuthors') ->attr({xmlns => ' my $xmlDataSet = $proxy->call($method); # my $xmlDataSet = $proxy->GetAuthors( ); # You can also do this my @authorsNodes = $xmlDataSet->valueof('//Authors'); foreach $author (@authorsNodes) { print $author->{'au_lname'}, ", ", $author->{'au_fname'}, "\n"; print "\t", $author->{'address'}, "\n"; print "\t", $author->{'city'}, ", ", $author->{'state'}, " ", $author->{'zip'}, "\n"; print "\t", $author->{'phone'}, "\n"; }
The output of this program is the following:
White, Johnson 10932 Bigge Rd. Menlo Park, CA 94025 408 496-7223 Green, Marjorie 309 63rd St. #411 Oakland, CA 94618 415 986-7020 . . .
Once the $proxy object is created, we call the GetAuthors web method knowing that the generated soapAction will be ` + `GetAuthors' and the location of the web service where SOAP::Lite library will try to contact is  Because this web method returns a DataSet, which translates to an XML document, we can parse it with XPATH-like syntax to obtain the list of authors and traverse the list to display the information for each author.
Now we want to call the GetBooksByAuthor web method as the second Perl program. This method takes one string parameter, the SSN for the author, and returns a DataSet object containing the author's name and all books he has published. The SOAP portion of the WSDL document states that the soapAction for this method is named  and the parameter is named sAuthorSSN:
use SOAP::Lite on_action => sub { sprintf '%s%s', @_ }; my $proxy = SOAP::Lite -> uri(' -> proxy(' my $method = SOAP::Data->name('GetBooksByAuthor') ->attr({xmlns => ' my @params = (SOAP::Data->name(sAuthorSSN => '998-72-3567')); my $xmlDataSet = $proxy->call($method => @params); my $author = $xmlDataSet->valueof('//Author'); print "Books by author:\n"; print $author->{'au_lname'}, ", ", $author->{'au_fname'}, "\n"; print $author->{'address'}, "\n"; print $author->{'city'}, ", ", $author->{'state'}, " ", $author->{'zip'}, "\n"; print $author->{'phone'}, "\n\n"; my @books = $xmlDataSet->valueof('//Books'); foreach $book (@books) { print "Type : ", $book->{'type'}, "\n"; print "Title : ", $book->{'title'}, "\n"; print "Price : \$", $book->{'price'}, "\n"; print "Notes : ", $book->{'notes'}, "\n"; print "\n"; }
Type perl yourPerlFile.pl to run the program. The output is:
Books by author: Ringer, Albert 67 Seventh Av. Salt Lake City, UT 84152 801 826-0752 Type : psychology Title : Is Anger the Enemy? Price : $10.95 Notes : Carefully researched study of the effects of strong emotions on the body. Metabolic charts included. Type : psychology Title : Life Without Fear Price : $7 Notes : New exercise, meditation, and nutritional techniques that can reduce the shock of daily interactions. Popular audience. Sample menus included, exercise video available separately.
As you can see, you can easily use any type of web service client to access a .NET web service. Clients of web services need to know how to communicate in HTTP and understand the WSDL. By the same token, you can develop a web service in any language and on any platform as long as it adheres to its WSDL specification.
Now that you have seen how simple it is to create and consume web services, we should let you in on a small but important pointthat XML web services is not the solution for everything. As responsible developers, we have to evaluate the requirements as well as the applicability of certain technology before applying it. On one hand, it's great to use web services as a way to expose legacy functionalities, or to enable integration of disparate systems on different locations, different platforms, or different companies. But there is no real reason to make a web service out of something that can be implemented as a simple component, or through .NET Remoting, which is discussed in Chapter 4. The decision is up to you. Again, the technology is just a tool; how you use it is another story.