HomeDigital EditionSys-Con RadioSearch Web Services Cd
B2B Beginning WS Business Process Management Case Studies Content Management Distributing Computing e-Business Electronic Data Interchange Enterprise Industry Insight Integration Interviews Java & Web Services .NET Portal Product Reviews Scalability & Performance Security SOAP Source Code UDDI Wireless WS Standards WS Tips & Techniques WSDL WS Editorials XML

Source Code for this article

Microsoft recently released the beta 1 of the SOAP Toolkit for Visual Studio version 2.0. While the new release still has some rough spots, the toolkit has provided developers with an easy way to deploy webservices, especially for those running on the Windows platform. Version 2 of the SOAP toolkit contains some drastic changes from its earlier version. Developers familiar with version 1 of the toolkit will know that it uses the Remote Object Proxy Engine (ROPE) for consuming webservices and the Web Service Description Language (WSDL) to define the contract for the Web service.

Specifically, the SOAP Toolkit 2 supports the following:

  • A SOAP client for developing a client-side application that consumes webservices
  • A SOAP Server for exposing the functionality of COM objects on the server
  • Complete support for the webservices Description Language (WSDL) 1.0 Specification
  • Universal Description, Discovery, and Integration (UDDI)
  • SOAP Specification version 1.1.
In this article, I illustrate the use of the MS SOAP toolkit to solve a real world problem. The example used here involves a book distributor that maintains a database of titles containing such information as pricing and publisher. At the moment, bookstores would make routine calls to the customer support of the distributor to check for the pricing of new titles. This method is time consuming and places a burden on the distributor, that could deploy its limited manpower for more productive tasks. Using webservices, the distributor can expose the functionality that allows anyone (in particular bookstore owners) to check for the pricing of books through the Internet.
We will build three components:
  • A COM object that accesses the database for querying the prices of books
  • A Web service that exposes the functionality of the COM object
  • A client application that consumes the Web service
For this article, I used Windows 2000 Advanced Server and IIS 5.0 on the server side and IE 5.5 on the client side.

Obtaining and Installing
The MS SOAP toolkit

The MS SOAP Toolkit for Visual Studio is available for download at: http://msdn. microsoft.com/xml The installation of the SOAP toolkit is straightforward. After installation, the toolkit can be found in the directory c:\program files\mssoapSDK. Three sub-folders are in this directory:

  • Binaries
  • Documentation
  • Samples
The Binaries folder contains the relevant DLLs as well as the WSDL generator. You will need the WSDL generator to simplify the process of creating the WSDL file, which is not a very pleasant thing to do by hand. The documentation folder contains the help file for the toolkit. The help file gives you an overview of how the toolkit works. The samples folder contains some VB and ASP samples. Note that there is no documentation for these samples and you are pretty much on your own. Read the HTML document that comes with them carefully for instructions on trying them out.

Configuring IIS For webservices
The first thing to do is to configure the Web server, IIS 5 in this case. For this article, I have created a virtual directory (see Figure 1).

Figure 1
Figure 1

The Demo virtual directory is mapped to c:\inetpub\soaptoolkit\demo.

Creating our COM Components using VB
Before we create our Web service, we must first create a COM component using Microsoft Visual Basic 6.0. The component that we are creating in this article is pretty simple. It basically contains a function that performs a search of books in a database. For simplicity, I use Access 2000 so that you can try out the examples yourself without the need for a database server.

Listing 1 shows the code for our COM component (in Visual Basic). Name the project BookStoreSystem and the class module Query (see Figures 2 and 3).

Figure 2
Figure 2
Figure 3
Figure 3

The function searchBook() takes in a single argument and outputs a string. Notice that the string returned is actually in XML format containing information about a book's title, ISBN, price, and publisher.

Once the code is created, compile the COM components (DLL) and be sure to note the following: Make sure that the DLL is compiled with the "Retained in Memory" and "Unattended execution" options. Also, once a COM component is compiled and used, any attempt to modify the code and re-create the DLL will encounter an error message (see Figure 4).

Figure 4
Figure 4

In this case, apart from rebooting your machine in order to release the DLL, you can do the following:

  • At the command prompt, type:
    C:\>net stop iisadmin /y
    to stop IIS
  • Next, recompile the COM component. Now the DLL can be overwritten.
  • Restart IIS by typing:
    C:\>net start w3svc
    Our Access table looks like Figure 5.

Figure 5

Using The WSDL Generator To Generate The WSDL And WSML Files
Once the COM component is generated, we are now ready to generate the WSDL and WSML files needed by the SOAP toolkit. To generate the WSDL and WSML files, invoke the wsdlgen application located in the Binaries folder.

When you click the OK button, the wsdlgen application will prompt you to select the interface of your COM object to expose as webservices. In our example, we have the Query interface (see Figure 7).

Figure 7
Figure 7

The wsdlgen application will generate two files: BookStoreSystem.wsdl and BookStore System.wsml. We will take a more detailed look at the two files a little later.

Building The SOAP Listener
Notice that the wsdlgen utility requires the URL of the SOAP Server: http://localhost/ demo/BookStoreSystem.asp

Where is this ASP file? We have to build it manually:

<% Response.ContentType="text/xml" %>
<%
set soapserver = Server.CreateObject("MSSOAP.SoapServer")
wsdl = Server.MapPath("BookStoreSystem.wsdl")
wsml = Server.MapPath("BookStoreSystem.wsml")

call soapserver.init(wsdl, wsml)
call soapserver.SoapInvoke(request, response)
%>
Save this ASP file in:
c:\inetpub\soaptoolkit\demo.

That's all you need to provide a Web service!

Creating The Consumer For The Web Service
A Web service provider without a consumer is useless. Let's now build our Web service consumer to test our newly built Web service. I use VBScript to build the consumer:

set soapclient = CreateObject("MSSOAP.SoapClient")
Call soapclient.mssoapinit("http://localhost/Demo/BookStoreSystem.wsdl",
"BookStoreSystem","BookStoreSystemPortType")

On Error Resume Next
wscript.echo soapclient.searchBook ("XML")
if soapclient.faultcode<>"" then
wscript.echo "soapclient.faultcode - " & soapclient.faultcode
wscript.echo "soapclient.faultstring - " & soapclient.faultstring
wscript.echo "soapclient.faultactor - " & soapclient.faultactor
wscript.echo "soapclient.detail - " & soapclient.detail
end if

Save the file as test.vbs. To test our Web service, simply type the following at the command prompt:
C:\inetpub\soaptoolkit\demo>cscript test.vbs
If everything goes well, you should see something like Figure 8. Note that in this example both the client and the server are on the same machine.

Figure 8
Figure 8

Understanding The Parts Involved
Now that our Web service is built and consumed, let's look back and see how the various parts work.

Web Server Description Language (WSDL)
The Web Server Description Language (WSDL) is an XML document that describes the services offered by a server. You can think of WSDL as a contract that specifies the services offered and how the client should package its request so that the services can be delivered properly (see Listing 2).

As you can see in Listing 2, the WSDL file contains the following five primary elements:

  • <types>
  • <messages>
  • <portType>
  • <binding>
  • <service>
For more information on the meaning of all these elements, refer to the SOAP documentation provided with the SOAP toolkit.

When a client wants to make use of a Web service, it first loads the WSDL file and uses the information contained in it to format a SOAP request. The WSDL and WSML (see below) are both generated by the wsdlgen utility, something that you won't want to do by hand!

You can choose to restrict the number of methods exposed by the COM object by modifying the relevant elements in the WSDL and WSML files.

Web Service Meta Language (WSML)
The Web Service Meta Language (WSML) file is specific to the current implementation of SOAP by Microsoft. It is used to map services described in the WSDL file to methods available in a COM object.

<?xml version='1.0' encoding='UTF-16' ?>
<!-- Generated 02/11/01 by Microsoft SOAP SDK WSDL File Generator, Version 1.0 -->
<servicemapping name='BookStoreSystem'>
<service name='BookStoreSystem'>
<using PROGID='BookStoreSystem.Query' cachable='0' ID='BookStoreSystemObject' />
<port name='BookStoreSystemPortType'>
<operation name='searchBook'>

<execute uses='BookStoreSystemObject' method='searchBook'

dispID='1610809344'>
<parameter callIndex='1'

name='searchStr' elementName='searchStr' />
<parameter callIndex='-1' name='retval' elementName='Result' />
</execute>
</operation>
</port>
</service>
</servicemapping>

The WSML file contains the <servicemapping> element that contains the <service> child element. The <service> element contains information on the COM component to be used (as indicated by the PROGID) as well as the method(s) to invoke (as indicated by the <operation> element).

The SOAP Listener
Since the Web server is providing a service, there must be a file that sits on the Web server to "listen" for an incoming request and to send back the results. This is the function of the BookStoreSystem.asp file we created earlier:

<% Response.ContentType="text/xml" %>
<%
set soapserver = Server.CreateObject("MSSOAP.SoapServer")
wsdl = Server.MapPath("BookStoreSystem.wsdl")
wsml = Server.MapPath("BookStoreSystem.wsml")

call soapserver.init(wsdl, wsml)
call soapserver.SoapInvoke(request, response) %>

The MS SOAP Toolkit provides the SOAP Server, which processes the incoming requests and responding with the results (see Figure 9).

Figure 9
Figure 9

Let's summarize the various steps that are involved:

  1. Client instantiates the SOAPClient object and requests the WSDL file
  2. Web server sends back the WSDL file to client
  3. Client uses the information in the WSDL file to build SOAP messages and sends the request to the ASP listener
  4. The listener instantiates the SOAPServer object and loads the WSDL and WSML files. The listener then executes the COM object whose methods are mapped to the WSDL file.
  5. The COM object returns the result to the listener
  6. The listener packages the result as a SOAP message and sends the SOAP message as a response back to the client
Tracing SOAP Packets
Throughout the entire process, we have not coded a single SOAP message because of the detail that the SOAP Toolkit encapsulates. While this is good when both the client and the server are running on Windows, it is not workable if the client is running on a non-Windows platform. In this case, you need to create the SOAP message on the client-side so that it can be sent to the server, and when the server responds with a SOAP message, you have to interpret it for the results. When I was toying with the toolkit, I was able to see the structure of the SOAP messages that were created, sent, and received. To do so, I use the tcpTrace utility, downloadable from http://www.pocketsoap.com/tcptrace/default.asp. The tcpTrace utility allows you to monitor the TCP traffic between your client and your server. In my test environment, I am running both my client and my server on the same machine; my trace setting is shown in Figure 10.

Figure 10
Figure 10

The setting indicates that all the traffic going into port 8080 will be redirected to port 80 and their contents will be monitored. To trace the traffic generated by our soap client, we need to modify the following two files:

1. Test.vbs:

Call soapclient.mssoapinit("http://localhost:8080/Demo/BookStoreSystem.wsdl",
"BookStoreSystem","BookStoreSystemPortType")
2. BookStoreSystem.wsdl

<soap:operation soapAction='http://localhost:8080/demo/bookstoresystem.asp' />
..
<soap:address location='http://localhost:8080/demo/bookstoresystem.asp' />
..

Once the two files are modified, I run the script again:
C:\inetpub\soaptoolkit\demo>cscript test.vbs
Immediately, two entries are displayed in the tcpTrace window (see Figure 11).

Figure 11
Figure 11

The first entry is when the soap client requests the WSDL file. This is shown by the GET request shown in the right-top window. The right-bottom window shows the WSDL file returned. Since the WSDL file is saved as a Unicode file, the tcpTrace utility is not able to display it.

The second entry shows the soap client sending a SOAP request to the server (shown in the right-top window). The SOAP request is:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<m:searchBook xmlns:m="http://localhost/demo/BookStoreSystem.xsd">
<searchStr>XML</searchStr>
</m:searchBook>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
The server also returns a SOAP message containing the results (shown in the right bottom window). This message is shown in Listing 3.

Since I have indicated in my COM object that my method searchBook() is going to return a string, the SOAP server will replace all XML reserved characters (like "<" and ">") with their respective entities.

Using The SOAP Client On The Web Browser
Having tested our Web service, let's now see how we can make use of this service in real life. Let's create a Web page that allows a bookstore owner to enter a search string so that the results can be obtained from the Web service (see Listing 4).

When a user keys in a search string, say "xml," the Web service is contacted and the following result will be shown:

Let's look at the listing in more detail:

'===Initialise the SOAP client===
set soapclient = CreateObject("MSSOAP.SoapClient")
call soapclient.mssoapinit("http://localhost/Demo/BookStoreSystem.wsdl",
"BookStoreSystem","BookStoreSystemPortType")
Since the SOAP toolkit objects aren't marked safe for scripting, you need to modify your IE settings to allow ActiveX objects not marked as safe to be created and used.

As our search result is returned as an XML string, I need to be able to extract the relevant information. The XML string returned is:

<Result>
<title>Professional JSP : Using JavaServer Pages, Servlets, EJB, JNDI, JDBC, XML, XSLT, and WML</title>
<isbn>1861003625</isbn>
<price>59.99</price>
<publisher>Wrox</publisher>
<title>Inside XML</title>
<isbn>0735710201</isbn>
<price>49.99</price>
<publisher>NewRiders</publisher>
<title>XML for the World Wide Web: Visual QuickStart Guide</title>
<isbn>0201710986</isbn>
<price>19.99</price>
<publisher>PeachPit</publisher>
</Result>
The easiest way to extract the relevant information is to use the XML DOM:
set xmldoc = CreateObject("MSXML2.DOMDocument")
'---load into a DOM---
xmldoc.loadxml (soapclient.searchBook(str1))
We then print out the books information using: xmldoc.documentElement.childnodes(i).text

where documentElement refers to the root element (<Result>) and the childnodes(i) refers to the child elements (<title><isbn><price><publisher>).

Conclusion
This article has touched on creating webservices using the Microsoft SOAP toolkit version 2 beta 1. webservices offer a lot of excitement for distributed computing developers, and for the next couple of months we are definitely going to see many more webservices created and deployed. Until the full release of the MS SOAP Toolkit is launched, we have time to start exploring this cool technology!

Author's Note:
At the time this article went to press, the Microsoft SOAP Toolkit version 2.0 Gold Release had just been released. There are minor changes to the beta release but overall things should look similar. Here are some of the changes:

  • Inclusion of a trace utility
  • Support for WSDL 1.1 standard
For more information and to download a copy of the Microsoft SOAP Toolkit 2.0, go to the following URL: http://msdn.microsoft.com/xml/default.asp

Author Bio
Wei Meng Lee is a writer, developer, and trainer specializing in XML and Web technologies. He is also a co-author for Wrox's Beginning WAP, WML and WMLScript and Manning's Dynamic WAP Application Development. Wei Meng spoke at the Wrox's Professional Wireless Developer conference as well as WirelessDevCon 2000. Wei Meng currently holds a full time job as a lecturer at Ngee Ann Polytechnic, Singapore.
[email protected]

Creating Web Services with the Microsoft SOAP Toolkit, by Wei Meng Lee
WSJ Vol 01 Issue 00 - pg.15

	


Listing 1

Public Function searchBook(searchStr As String)
As String
 Dim conn As New Connection
 Dim rs As New Recordset
 Dim connStr, sql, xmlStr As
String
 Dim discount As Integer

 connStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\InetPub\SOAPToolkit\Demo\Distributor.mdb;Persist Security Info=False"
 conn.Open
connStr
 sql = "SELECT
* FROM Books WHERE Title LIKE '%" & searchStr & "%'"

 Set rs = conn.Execute(sql)
 xmlStr = "<Result>"
 While Not
rs.EOF

xmlStr = xmlStr & "<title>" & Trim(rs("Title")) & "</title>"

xmlStr = xmlStr & "<isbn>" & Trim(rs("ISBN")) & "</isbn>"

xmlStr = xmlStr & "<price>" & Trim(rs("Price")) & "</price>"

xmlStr = xmlStr & "<publisher>" & Trim(rs("Publisher"))
& "</publisher>"

rs.MoveNext
 Wend
 xmlStr = xmlStr
& "</Result>"
 searchBook
= xmlStr

 rs.Close
 conn.Close
 Set rs = Nothing
 Set conn =
Nothing
End Function

Listing 2

<?xml version='1.0' encoding='UTF-16'
?>
<!-- Generated 02/11/01 by Microsoft
SOAP SDK WSDL File Generator, Version 1.0 -->
<definitions name ='BookStoreSystem'
targetNamespace = 'http://localhost/demo/BookStoreSystem.wsdl'

xmlns:tns='http://localhost/demo/BookStoreSystem.wsdl'

xmlns:xsd1='http://localhost/demo/BookStoreSystem.xsd'

xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'

xmlns='http://schemas.xmlsoap.org/wsdl/'>
 <types>
 <schema targetNamespace='http://localhost/demo/BookStoreSystem.xsd'
 xmlns='http://www.w3.org/1999/XMLSchema'>
 </schema>
 </types>
 <message name='searchBook'>
 <part name='searchStr'
type='string'/>
 </message>
 <message name='searchBookResponse'>
 <part name='searchStr'
type='string'/>
 <part name='Result'
type='string'/>
 </message>
 <portType name='BookStoreSystemPortType'>
 <operation name='searchBook'
parameterOrder='searchBookInOut1'>
 <input
message='tns:searchBook' />
 <output
message='tns:searchBookResponse' />
 </operation>
 </portType>
 <binding name='BookStoreSystemBinding'
type='tns:BookStoreSystemPortType' >
 <soap:binding style='document'
transport='http://schemas.xmlsoap.org/soap/http' />
 <operation name='searchBook'
>
 <soap:operation
soapAction='http://localhost/demo/bookstoresystem.asp' />
 <input>

<soap:body use='encoded' namespace='http://localhost/demo/BookStoreSystem.xsd'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' />
 </input>
 <output>

<soap:body use='encoded' namespace='http://localhost/demo/BookStoreSystem.xsd'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' />
 </output>
 </operation>
 </binding>
 <service name='BookStoreSystem'
>
 <port name='BookStoreSystemPortType'
binding='tns:BookStoreSystemBinding' >
 <soap:address
location='http://localhost/demo/bookstoresystem.asp' />
 </port>
 </service>
</definitions>

Listing 3

<?xml version="1.0" encoding="UTF-8"
standalone="no"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
 <SOAP-ENV:Body>
 <m:searchBookResponse
xmlns:m="http://localhost/demo/BookStoreSystem.xsd">

<searchStr>XML</searchStr>

<Result><Result><title>Professional
JSP : Using JavaServer Pages, Servlets, EJB, JNDI, JDBC, XML, 
XSLT, and WML</title>
<isbn>1861003625</isbn>
<price>59.99</price>
<publisher>Wrox</publisher>
<title>Inside XML</title>
<isbn>0735710201</isbn>
<price>49.99</price>
<publisher>NewRiders</publisher>
<title>XML for the World Wide Web: Visual QuickStart Guide</title>
<isbn>0201710986</isbn>
<price>19.99</price>
<publisher>PeachPit</publisher>
</Result>

</Result>
 </m:searchBookResponse>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.

  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.