UDDI Inquiry with Windows CE .NET

 

Abdul Rasheed Usman
Microsoft Corporation

November 2002

Applies to:
    Microsoft® Windows® CE .NET
    Universal Description, Discovery, and Integration (UDDI)
    SOAP
    Extensible Markup Language (XML)
    Web Services

Download Winceuddi.exe.

Summary:   With the proliferation of useful and exciting Web Services, the capability to easily locate and consume Web Services has become increasingly important. To address this need, the SOAP Toolkit is available as an operating system feature in Windows CE .NET. This article and the accompanying samples give a brief introduction to Web Services and the SOAP Toolkit on Windows CE .NET, and demonstrates how to use the SOAP Toolkit to make UDDI inquiries. For an operating system like Windows CE .NET, which targets a broad range of intelligent devices, such capabilities will open up a plethora of opportunities. (18 printed pages)

Contents

Introduction
XML Web Services
Windows CE .NET SOAP Toolkit
A Brief Introduction to UDDI
UDDI Inquiry APIs
Composing the UDDI Inquiry APIs with the SOAP Toolkit
The UDDIApi and UDDIFindBusiness Samples
Building the Samples
Searching for Businesses with the UDDIFindBusiness Sample
Problems Encountered
Conclusion
Resources

Introduction

Imagine being able to automatically populate most of the contact information in a contact list management application on a mobile device, this enables a mobile business professional the ability to identify and locate possible customers, partners, and competitors with the click of a button. Or, imagine a purchase application that gets the best price for a product by querying competing vendors who expose standard XML Web Services. UDDI Inquiry and XML Web Services promise such exciting capabilities and more for devices running Microsoft Windows CE .NET. This article and the accompanying samples will show you how to consume Web Services, and specifically how to make UDDI inquiries, from an application running on Windows CE .NET.

**Note   **This article and the accompanying samples are based on UDDI version 1, and assume that you are familiar with the Windows CE .NET operating system, its development tools, Microsoft Platform Builder, XML, and SOAP.

XML Web Services

Web Services are based on a set of industry standard protocols, including Web Services Description Language (WSDL), SOAP, XML, and Hypertext Transfer Protocol (HTTP), that make it very easy for systems to talk to each other in a platform-independent manner. This, in many respects, is very similar to the way the Internet works today. For example, a Web browser doesn't need to know about the operating system being used by an Internet server, because the client and server are both using the same underlying protocols. The Web browser experience involves presentation of data from remote systems, while XML Web Services pertain to the manner which arbitrary computing systems talk to each other based on a set of open protocols that can be implemented on any device, operating system, language, or object model. XML Web Services allow broad interoperability regardless of the underlying technologies, and also provide a loosely coupled programming model. Rather than a distributed object model using complex runtimes at each end, Web Services use a message-based system.

Stand-alone, monolithic applications are difficult to customize or extend. The use of Component Object Model (COM), DCOM, and other distributed object technologies makes customization and extension of applications simpler, but also brings its own problems. Configuring DCOM to run across firewalls, for example, can be difficult. Embedded systems are becoming smarter, and are increasingly shipping with network connectivity, so it is extremely useful to be able to remotely configure or monitor an embedded device, or have an embedded system integrate with other systems on a local network or the Internet. Web Services use HTTP, the widely available lowest common denominator for Internet-based communication. This makes it simple to create a Web Service client or server running on Windows CE .NET.

The underlying protocols used by Web Services are simple, extensible, and widely available. We communicate with Web Services by exchanging SOAP messages, the formats of which are defined in WSDL files. SOAP is an XML-based protocol for exchange of structured and typed information in a decentralized and distributed environment. SOAP defines the message format, how the message is processed, encoding rules for representing instances of application-defined data types, and a mechanism to represent remote procedure calls and responses. SOAP messages can be exchanged over a variety of protocols, the most popular being HTTP. WSDL is an XML-based language for describing network services as collections of communication endpoints capable of exchanging messages, and can describe services regardless of the message formats or the network protocols used to communicate.

Windows CE .NET SOAP Toolkit

The Microsoft Windows CE .NET SOAP Toolkit is currently the only way to consume and produce XML Web Services on Windows CE .NET. The introduction of .NET Compact Framework will certainly make creation of Web Service-enabled client applications simpler, but will also carry a payload of approximately 1 MB for the .NET Compact Framework runtime components. Therefore, creating these applications in C/C++ with the SOAP Toolkit may still be an attractive option for small-footprint embedded devices. Windows CE .NET is a componentized, embedded operating system, and the SOAP Toolkit is componentized into separate client and server components that can be independently selected as features of the Windows CE .NET platform. Selecting one of these features may also bring features like COM, XML, and the HTTPD Web Server into the platform. Developing Web Service clients and COM objects to host Web Services is easily accomplished by using Platform Builder and Microsoft eMbedded Visual C++®.

The SOAP Toolkit consists of:

  • A client-side object that allows applications to invoke Web Services.
  • A server-side object that maps invoked Web Service functions to COM object method calls as described by WSDL and Web Services Meta Language (WSML) files for the Web Service.
  • A set of objects to construct, transmit, read, and process SOAP messages.

You can easily access and program the COM objects implemented by the SOAP Toolkit by using the Active Template Library (ATL) or Microsoft Foundation Classes (MFC), which you may already be familiar with. The easiest way to invoke a Web Service by using the SOAP Toolkit is to use the high-level SOAPClient object. After this object is initialized with the location of the WSDL file for the Web Service (this can be the location of a cached local copy of the WSDL file), all the Web Service operations defined in the WSDL file can be invoked just like any other method call on the object. The alternative method is to use the low-level HttpConnector, SoapSerializer, and SoapReader objects. The low-level APIs require more coding, but offer finer control over the construction of the SOAP message. The low-level APIs are used in the sample code that accompanies this article.

This article provides an introduction to UDDI, and also explores how to use the Windows CE .NET SOAP Toolkit low-level objects to construct, transmit, and receive SOAP messages from the UDDI Web Service. UDDI is used as the sample Web Service because it offers the means to publish and discover standard Web Services through the use of SOAP requests and responses.

A Brief Introduction to UDDI

UDDI is a group of Web-based registry operators that provide information about businesses and the services they provide. It is a logically centralized and physically distributed service with multiple root nodes (UDDI operator sites) that replicate data with each other regularly. A business can register with any UDDI operator and the registered information will get propagated to all operators. It is also possible for an enterprise to run a private UDDI service for intranet or extranet use. This can be accomplished by using Enterprise UDDI Services available in Windows Server 2003. The information that can be registered consists of:

  • White pages data containing addresses, contacts, and known identifiers.
  • Yellow pages data containing industrial categorizations based on standard taxonomies.
  • Green pages data containing technical information about the services exposed by the business.

UDDI also defines APIs which are used to publish and discover information in the UDDI business registry. These functions are defined and exposed as SOAP messages. This allows for the programmatic discovery of businesses and their services. Also, Web Services that are described by using standard WSDL files can be registered in the UDDI registry. This allows for the programmatic discovery and binding of services, both at design time and at run time. This aspect of UDDI is very exciting. Web Service clients can locate Web Services offered by multiple service providers and can choose one service provider over another at runtime, based on many parameters, including, cost, location, and the services being provided.

UDDI defines the core information model used by the UDDI registries as an XML schema describing four core types of information:

  • Business information
  • Service information
  • Binding information
  • Metadata information

These information types are represented by using the businessEntity, businessService, bindingTemplate, and tModel XML elements, respectively. Figure 1 shows the relationship between these core XML elements.

Figure 1. UDDI core information elements and their relationships.

The businessEntity element serves as the container for all of the information related to a business unit, with complex business units being registered as separate business entities. The information contained in the businessEntity structure allows you to search and locate businesses by supplying all or part of the "white pages" and "yellow pages" data about a business. Each businessEntity structure can contain one or more businessService elements.

The businessService element is used to group a series of related services that are related to a business process or category of services. It also allows for the categorization of the service by industry, product, service, or geographic boundaries. Each businessService can contain one or more bindingTemplate elements.

The bindingTemplate element contains technical information about the service. This includes information about where to access the service and information that describes the service. In addition, it can contain a list of references to information about specifications that form the technical fingerprint of the service and state that the service implements a specific behavior or programming interface. These references are a collection of keys that can be used to access metadata information about a specification, in the form of an element called tModel.

The tModel element contains metadata which defines a service specification, including name, publisher information, and URL pointers to the actual technical specification that defines the service. This allows for many services to conform to the same registered tModel. In the case of a Web Service, tModel will point to the WSDL file for the Web Service. Together, the businessService, bindingTemplate, and tModel contribute to green pages data about services that are provided by businesses.

UDDI Inquiry APIs

The UDDI Inquiry APIs, exposed as SOAP messages, can be used to locate businesses, services, and service specifications. The find_xxx APIs allow you to search the registry by specifying various search criteria. You can use the get_xxx APIs to get up-to-date and complete registered details when actual keys to instances of specific structures (for example, businessEntity, businessService, bindingTemplate, and tModel) are known. The UDDI Inquiry can be made to any UDDI operator. Table 1 lists the publicly accessible UDDI Inquiry APIs as defined by UDDI.

Table 1. UDDI Inquiry APIs, their purpose, and messages they return.

Composing the UDDI Inquiry APIs with the SOAP Toolkit

The Windows CE .NET SOAP Toolkit includes all the components necessary to construct, transmit, read, and process SOAP messages. In this section we will learn how to use the SOAP toolkit to make a simple UDDI inquiry by using the find_business API. You can call additional UDDI Inquiry APIs, or other arbitrary Web Services, in a similar manner.

You can use the find_business API to perform broad searches for information about businesses in the UDDI registry, and it will return a businessList message matching the supplied search arguments. The find_business API allows a wide range of queries through the use of a collection of optional arguments. The UDDI Specifications contain the definition of all UDDI Inquiry APIs, their arguments, and their return messages.

Based on the definition of the find_business API given in the UDDI XML schema, you can use the SOAP Toolkit to compose a request, post the request to a UDDI operator, and get the response. The code you can use to achieve this is shown in Code Listing 1.

Code Listing 1 shows how you can construct an appropriate SOAP message to call the UDDI find_business API. You can use an ATL console application to illustrate the required steps. In this sample, you are searching for a company named "Litware Book Distribution Inc."

Notes   A detailed discussion of COM, ATL, and SOAP Toolkit objects is beyond the scope of this article.

To keep the code listing small, it does not handle any error returns.

Code Listing 1. Code using SOAP Toolkit objects to make a simple find_business inquiry.

#include <windows.h>
#include <atlbase.h>
#include <msxml.h>
#include <mssoap.h>
#include <tchar.h>

int main(int argc, char *argv[], char *envp[])
{
   CComPtr<IXMLDOMDocument> pDocu = NULL;
   CComPtr<ISoapSerializer> pSeri = NULL;
   CComPtr<ISoapConnector>  pConn = NULL;
   CComPtr<ISoapReader>     pRead = NULL;
   CComPtr<IStream>         pIStream = NULL,pOStream = NULL;

   VARIANT_BOOL vbSuccess = FALSE;
   CComVariant  varTemp;
   CComBSTR     bstrXML;

   CoInitializeEx(NULL,COINIT_MULTITHREADED);

   pConn.CoCreateInstance(__uuidof(HttpConnector));
   pSeri.CoCreateInstance(__uuidof(SoapSerializer));
   pRead.CoCreateInstance(__uuidof(SoapReader));

   //Reset the HttpConnector and SoapSerializer objects
   pConn->Reset();
   pSeri->reset();

   //Set the connector properties
   varTemp = CComBSTR(L"http://uddi.microsoft.com/inquire");
   pConn->put_Property(CComBSTR(L"EndPointURL"),varTemp);
   varTemp = CComBSTR(L"");
   pConn->put_Property(CComBSTR(L"SoapAction"),varTemp);

   //Initialize the connector and signal the start of SOAP message
   pConn->Connect();
   pConn->BeginMessage();

   //Initialize the serializer object
   pConn->get_InputStream(&pIStream);
   varTemp = pIStream;
   pSeri->Init(varTemp);

   //Compose find_business API as a SOAP message

   //<envelope>
       pSeri->startEnvelope(NULL,CComBSTR(L"NONE"),NULL);
   //<body>
   pSeri->startBody(NULL);
   //<find_business>
   pSeri->startElement(CComBSTR(L"find_business"),NULL,NULL,NULL);
   //UDDI API version attribute
   pSeri->SoapAttribute(CComBSTR(L"generic"),NULL,CComBSTR(L"1.0"),NULL);
   //Default name space
   pSeri->SoapAttribute(CComBSTR(L"xmlns"),NULL,
     CComBSTR(L"urn:uddi-org:api"),NULL);
   //<name>
   pSeri->startElement(CComBSTR(L"name"),NULL,NULL,NULL);
   pSeri->writeString(CComBSTR(L"Litware Book Distribution Inc"));
   pSeri->endElement();
   //</name>
   pSeri->endElement();
   //</find_business>
   pSeri->endBody();
   //</body>
   pSeri->endEnvelope();
   //</envelope>

   //Send the SOAP message
   pConn->EndMessage();

   //Get the response message into the SoapReader object
   pConn->get_OutputStream(&pOStream);
   varTemp = pOStream;
   pRead->load(varTemp,CComBSTR(L""),&vbSuccess);

   //Display the result
   pRead->get_DOM(&pDocu);
   pDocu->get_xml(&bstrXML);
   OutputDebugString(bstrXML);

   varTemp = NULL;
   pRead = NULL;
   pSeri = NULL;
   pConn = NULL;
   pDocu = NULL;
   pIStream = NULL;
   pOStream = NULL;

   CoUninitialize();

   return 0;
}

Code Listing 1 begins by declaring ATL smart pointer variables for the interface pointers and other ATL type variables. After initializing the COM library by calling CoInitializeEx, the code creates the HTTPConnector, SoapSerializer, and SoapReader objects by calling CoCreateInstance methods on the smart pointers that were declared for the ISoapConnector, ISoapSerializer, and ISoapReader interfaces. Now, pConn will contain a pointer to the ISoapConnector interface that is exposed by the HttpConnector object, pSeri will contain a pointer to the ISoapSerializer interface that is exposed by the SoapSerializer object, and pRead will contain a pointer to the ISoapReader interface that is exposed by the SoapReader object. These interface pointers can invoke methods on their objects. Next, the HttpConnector and SoapSerializer objects are reset by calling their Reset methods. This must be done when reusing objects.

To use the HttpConnector object to send or receive SOAP messages over HTTP, set appropriate properties and initialize this object. The URL of the remote server to POST the SOAP message to is http://uddi.microsoft.com/inquire. If you want to POST the find_business inquiry to a different UDDI operator, you can use the URL for that UDDI operator instead. The SoapActionHTTP header field is also set to an empty string, as required by UDDI. When SOAP messages are exchanged over HTTP, SOAP uses the SoapAction header field to indicate the intent of the SOAP HTTP request, and UDDI requires that this field be an empty string. To learn about the other properties that you can set for the HttpConnector object, refer to the SOAP Toolkit documentation. After all required properties are set, initialize the HttpConnector object and signal that you are about to construct a SOAP message by calling the Connect and BeginMessage methods.

To initialize the SoapSerializer object, you call the Init method and pass the IStream interface pointer, which is returned by the read-only InputStream property of the HttpConnector object, as an argument. This IStream interface pointer provides access to the data stream that will be sent to the server by the HttpConnector object. Now, SOAP messages constructed or serialized by using the SoapSerializer object will be written to the HttpConnector object's stream, that sends data to the server.

Next, construct the find_businessinquiry SOAP message by using the SoapSerializer object. Begin by calling startEnvelope and startBody. This signals the beginning of the <Envelope> and <Body> element of the SOAP message. Next, start a <find_business> element by calling the startElement method. Also, set a "generic" attribute for this element with a value of "1.0", and the "xmlns" default namespace attribute with a value of "urn:uddi-org:api", by calling the SoapAttribute method. The "generic" attribute's value specifies the version of UDDI that is used for the <find_business> element, and the "xmlns" attribute's value specifies the default name space being used for the <find_business> element. To specify that you want to locate businesses with the name "Litware Book Distribution Inc", begin a <name> element by calling the startElement method, and write the business name as the content of the <name> element by calling the writeString method. You can specify some other business name here if you want. Then, close the <name> and <find_business> elements by matching the startElement with an endElement. The format of the <find_business> element and the elements that you constructed within it is based on UDDI XML schema. Now, to complete the SOAP message construction, close the <Body> and <Envelope> elements by calling the endBody and endEnvelope methods, respectively.

A complete SOAP message is now being serialized to the input stream of the HttpConnector object. You can have the HttpConnector send it to the remote server by calling the EndMessage. This method call will cause the HttpConnector object to send the serialized SOAP message to the remote server and receive any response that the remote server returns.

To examine the response returned by the remote server, initialize the SoapReader object by calling the load method, and pass the IStream interface pointer returned by the read-only OutputStream property of the HttpConnector object as an argument. This IStream interface pointer provides access to the data stream that was returned by the remote server to the HttpConnector object. Now, you can call various methods supported by the SoapReader object to look at the response obtained from the remote server. It is simplest to get just the read-only IXMLDOMDocument interface pointer representing the response. The response from the remote server is expected to be a SOAP response message and, therefore, an XML document. Extract the XML, and output the contents to the debugger by using OutputDebugString.

Because you are finished with the interface pointers that are stored in the ATL smart pointers, you can force their release by assigning NULL to each of the smart pointers that you were using. This will cause each smart pointer to call Release on the interface pointer that it was storing. Then, you can safely close the COM library with a call to CoUninitialize, and return.

The code shown in Code Listing 1 will post the SOAP request shown in Code Listing 2 to the Microsoft UDDI operator end point http://uddi.microsoft.com/inquire. The SOAP message shown in Code Listing 2 was obtained from a packet captured by running the Network Monitor tool (NetMon). You can see that the SOAP request contains the find_business inquiry wrapped inside the SOAP body.

Code Listing 2. SOAP request with a simple find_business inquiry.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="https://schemas.xmlsoap.org/
soap/encoding/" xmlns:SOAP-ENV="https://schemas.xmlsoap.org/
soap/envelope/">
<SOAP-ENV:Body>
<find_business generic="1.0" xmlns="urn:uddi-org:api">
<name>Litware Book Distribution Inc</name>
</find_business>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>               

When the code in Code Listing 1 is executed, the Microsoft UDDI operator end point returns the SOAP response shown in Code Listing 3. As expected, the listing contains a businessList message that matches the search arguments, wrapped inside the SOAP body. Note that the returned <businessList> element contains only one <businessInfo> element inside the <businessInfos> element. That is because you searched for businesses by specifying the complete name of a business, and there was only one business with that name registered in the UDDI registry. If you specify part of a business, for example "Lit", there will be multiple <businessInfo> elements, one for each business whose name starts with "Lit".

Code Listing 3. SOAP response received for the simple find_business inquiry.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<businessList generic="1.0" operator="Microsoft Corporation" 
truncated="false" xmlns="urn:uddi-org:api">
<businessInfos>
<businessInfo businessKey="c51f956a-447a-4bd4-babc-e0298ba39d13">
<name>Litware Book Distribution Inc</name>
<description.xml:lang="en">Fictional company used by Microsoft NES
</description>
<serviceInfos>
<serviceInfo serviceKey="b197be4e-91d7-44e8-84db-44df43540436" 
businessKey="c51f956a-447a-4bd4-babc-e0298ba39d13">
<name>Litware Catalog</name>
</serviceInfo>
</serviceInfos>
</businessInfo>
</businessInfos>
</businessList>
</soap:Body>
</soap:Envelope>

The UDDIApi and UDDIFindBusiness Samples

Two code samples accompany this article. The first is UDDIApi, a sample implementation of the UDDI Inquiry APIs as a set of scriptable ATL COM objects (except find_relatedBusiness, which is left as an exercise for the reader). These objects use the SOAP Toolkit to compose and transmit SOAP requests. Each object in UDDIApi implements one UDDI Inquiry API. Various arguments to the UDDI Inquiry API can be set as properties on the object and by invoking methods on the object. The result of the UDDI inquiry can be obtained as a read-only IXMLDOMElement property of the object, and the returned IXMLDOMElement object will contain the expected UDDI inquiry return element, or SOAP Fault element in the case of errors. You can easily verify from the source code for each object in UDDIApi that it is quite easy to compose SOAP messages using SOAP Toolkit objects for complex tasks such as UDDI Inquiry.

Code Listing 4 shows how to make the same simple find_business inquiry shown in Code Listing 1, this time by using the objects implemented in UDDIApi. The other UDDI Inquiry APIs can be invoked in a similar manner. It is quite straightforward, and it is left for you to explore them.

Code Listing 4. Code to make a simple find_business inquiry by using objects provided in the UDDIApi sample.

#include <objbase.h>
#include <initguid.h>
#include <windows.h>
#include <atlbase.h>
#include <msxml.h>
#include <mssoap.h>
#include <tchar.h>
#include <uddiapi.h>

int main(int argc, char *argv[], char *envp[])
{
   CComPtr<IXMLDOMElement>      pElem = NULL;
   CComPtr<ISTKConnectorProps>  pProp = NULL;
   CComPtr<IFindBusiness>       pBusi = NULL;

   CComBSTR bstrXML;

   CoInitializeEx(NULL,COINIT_MULTITHREADED);

   pProp.CoCreateInstance(__uuidof(STKConnectorProps));
   pBusi.CoCreateInstance(__uuidof(FindBusiness));

   //Initialize the connector properties
   pProp->put_EndPointURL(CComBSTR(L"http://uddi.microsoft.com/inquire"));

   //Initialize the FindBusiness object
   pBusi->put_STKConnectorProps(pProp);
   pBusi->put_name(CComBSTR(L"Litware Book Distribution Inc"));

   //Make the find_business enquiry
   pBusi->get_findResult(&pElem);

   //Display the result
   pElem->get_xml(&bstrXML);
   OutputDebugString(bstrXML);

   pElem = NULL;
   pBusi = NULL;
   pProp = NULL;

   CoUninitialize();

   return 0;
}

The second accompanying sample, UDDIFindBusiness, is a sample MFC application that uses objects implemented in UDDIApi to make complex find_business inquiries and get details about businesses and the services they provide. UDDIFindBusiness permits you to specify all or any allowed find_business arguments before making the inquiry, and demonstrates use of the UDDI Inquiry APIs find_business, get_businessDetail, and get_serviceDetail.

Building the Samples

You can build and try out the samples by creating a custom Windows CE .NET OS image for the Windows CE Emulator. You will need Platform Builder version 4.1 or later with support for the Emulator installed, and you should be equipped to create, build, and debug custom Windows CE .NET OS images for the Emulator. If you would like to try out the samples on other supported board support packages (BSPs), the steps are similar.

Start by building a custom Windows CE .NET operating system image for the Emulator by performing the following steps:

  1. Launch the Platform Builder application.
  2. From the File menu, click New Platform.
  3. In the New Platform Wizard, click Next.
  4. From the list of available BSPs, select Emulator:X86, and then click Next.
  5. From the list of available platform configurations, select Retail Point-of-Sale Device.
  6. In the Platform Name box, type UDDIPlatform as the name for your platform, and then click Next.
  7. From the list of Retail Point-of-Sale Device variants, select Retail Point-of-Sale Workstation, and then click Next.
  8. To accept the default selections for Application & Media, click Next.
  9. To accept the default selections for Networking & Communications, click Next.
  10. In the Special Feature Notification dialog box, click Next.
  11. On the Congratulations page, click Done to close the New Platform Wizard.
  12. In the FeatureView of the Platform Builder, go to UDDIPlatform, then to Retail Point-of-Sale Device, and then to Application & Services Development. Make sure these features exist: Active Template Library, Microsoft Foundation Classes, and Client under Simple Object Access Protocol Toolkit. If one of these does not exist, add that feature to the platform.
  13. From the Build menu, click Set Active Configuration.
  14. From the list of platform configurations, select UDDIPLATFORM – Emulator: X86 Win32 (WCE emulator) Release, and then click OK.
  15. From the Build menu, click Build Platform.

This will create a custom Windows CE .NET operating system image, built as a Release image for Emulator, with all the necessary Windows CE .NET features to try out the samples. If you would like to try out the samples on other configurations, make sure that your configuration contains the Active Template Library, Microsoft Foundation Classes, and SOAP Toolkit Client features.

To build the samples, download and unzip the UDDIApi and UDDIFindBusiness source files to separate folders named UDDIApi and UDDIFindBusiness, under the parent folder named UDDIPlatform that was created when building the platform discussed above. (You can also download and unzip FindB and FindBWithUDDIApi, the source files for the code listings in Code Listing 1 and Code Listing 4, respectively.) The folders must be under the same parent folder because UDDIFindBusiness depends on the uddiapi.h header file that will be generated while building UDDIApi, and it is easy for UDDIFindBusiness project settings to refer to this file if they are under the same parent folder. Each of the samples has a Platform Builder 4.1 project file, with the extension .pbp, that has all the required settings enabled, so you can add them to the platform that you created in the previous procedure and build the samples immediately. You must also be able to register the UDDIApi DLL. This can be accomplished by building the regsvr32.exe sample utility, using the source code that is available in the folder named PUBLIC\DCOM\SDK\SAMPLES\REGSVR in your Windows CE .NET installation. Add the projects UDDIApi, UDDIFindBusiness, and regsvr32 utility to the platform by performing the following steps for each of them:

  1. From the Project menu, click Insert, and then click Existing Project.
  2. In the Insert Existing Project box, browse to the folder for the project, select the project's .pbp file, and then click OK.

Also, to make sure that UDDIApi is built before UDDIFindBusiness, make UDDIFindBusiness dependent on UDDIApi in the Project Dependencies box by choosing Dependencies under Project. Now, build the projects by performing the following steps:

  1. From the Build menu, click Batch Build.
  2. In the Batch Build box for each project, from the list of Project configurations, select the Project configuration for EMULATOR: X86 Win32 (WCE emulator) Release, clear the check boxes for rest of the configurations, and then click Build.

These steps should build the projects with no errors or warnings, and will copy the output files to your flat release directory. This can easily be verified by selecting Build and Open Build Release Directory, and then using Dir to locate the files. After downloading the Windows CE .NET image to the Emulator, register the UDDIApi DLL by typing s regsvr32 uddiapi.dll at the Windows CE > prompt. Now, you are ready to search for businesses by using the UDDIFindBusiness sample application. First, launch the application by typing s uddifindbusiness at the Windows CE > prompt, or by using Target and Run Program.

Note   For instructions on how to configure the Emulator, refer to the Platform Builder documentation.

Searching for Businesses with the UDDIFindBusiness Sample

Using the UDDIFindBusiness sample to search for businesses is easy. Figure 2 shows the user interface of this dialog-based application running on the Windows CE .NET Emulator.

Figure 2. Searching for businesses by using the UDDIFindBusiness sample application.

To search for businesses, start by specifying the find_business API arguments. Simple arguments to the API, like the business name or part of a business name and findQualifiers, can be specified in the main dialog box itself. Advanced arguments, such as identifierBag, categoryBag, tModelBag, and discoveryURLs, can be specified in the Advanced Parameters dialog box, shown in Figure 3, by clicking on the Adv. button. Also specify the UDDI operator end point and any proxy information if your computer is connected to the Internet through a proxy server. When you click the Find button, the application will populate the treeview control on the left side of the window with the names of all the businesses that the UDDI operator returned as a match for your search. It will also populate names of the services that each business has registered as subnodes for each business. If you get an empty treeview for your search, select the Info. in XML Format checkbox and perform the search again to see the exact message that the UDDI operator is returning.

Figure 3. Dialog box to specify advanced arguments for the search.

To get more details about a business or a service that a business provides, select the business or service in the treeview control and click the Info. button. This will populate the edit control on the right side of the window with more details about the selected business or service, as returned by the UDDI operator.

UDDI search with the UDDIFindBusiness sample application can become quite interesting if you start searching by specifying combinations of arguments. Keep exploring!

Problems Encountered

UDDI requires that the SOAPAction HTTP header field, which is required by SOAP 1.1 when sending a SOAP message over HTTP, be an empty string surrounded by quotes. Also, because UDDI operators are required to support only UTF-8 encoding, you must specify UTF-8 encoding as the optional charset parameter in the Content-type HTTP header field of the SOAP requests that you POST for UDDI Inquiry.

Unfortunately, the HTTPConnector object currently available in the Windows CE. NET SOAP Toolkit has no way of specifying these parameters. The put_Property method call on the HttpConnector object seems to fail if an empty string is set as the value for the SoapAction property, and the HttpConnector object does not seem to specify the charset parameter with the encoding type value specified when calling the startEnvelope method of the SoapSerializer object.

The samples accompanying this article worked around these hurdles by implementing a very crude and primitive connector object, the HTTPConn object, instead of using the HTTPConnector object implemented by the SOAP Toolkit**.**

Conclusion

This article introduces the concepts of consuming Web Services from a Windows CE .NET application. UDDI Inquiry, and other important Web Services which can be located through UDDI Inquiry, can bring tremendous value to your Windows CE .NET-based solution. Imagine building a travel kiosk based on Windows CE .NET, to be used at airports, train stations, and other transport locations. The kiosk could include support for Multilingual User Interface (MUI) and therefore provide its user interface in a range of languages. The kiosk could provide travel, hotel, and local information services, each of which is dynamically consumed from Internet-based XML Web Services. Car rental and hotels could be linked to flight arrival times, and hotels could be booked based on appointments in users' calendars, which could also be exposed by using XML Web Services. This article and accompanying samples provide just a glimpse of what can be achieved by using Windows CE .NET and XML Web Services.

Resources

Windows CE .NET SOAP Toolkit documentation

SOAP specifications

WSDL specification

UDDI specifications

Microsoft UDDI site