Discovery Mechanisms for Web Services

UDDI

To establish an electronic relationship with Contoso, Fabrikam Wing Nuts needs to obtain information about the Web services that Contoso Motor Company supports. It would be ideal if Contoso could publish the technical details in such a way that any supplier interested in doing business with Contoso could easily obtain them.

UDDI provides a central directory service for publishing technical information about Web services. UDDI is the result of an industry initiative backed by a significant number of technology companies, including Microsoft, IBM, and Ariba. (You can find a full list of participants in the UDDI initiative at http://www.uddi.org/community.html.)

UDDI is yet another example of the unprecedented level of industry cooperation around the adoption of Web services. Many companies believed that a directory service for advertising Web services would be crucial to Web services gaining critical mass, and they felt that the time needed to develop the UDDI specification through a standards body was unacceptable.

As a result, the UDDI specification and the infrastructure required to support it were developed cooperatively by a number of companies. Once UDDI has reached “a reasonable level of maturity,” the project members have committed to submitting the UDDI specification to a standards body.

UDDI Architecture

The infrastructure that supports UDDI is composed of a set of registries and registrars. A registry contains a full copy of the UDDI directory; a registrar provides UDDI registration services on behalf of a customer.

A registrar can be an ISP, a host of a business-to-business (B2B) marketplace, an individual company, or the host of a registry itself. For example, Microsoft offers a registry and also provides an HTML UI for creating and maintaining records within the directory. Contoso could also serve as a registrar in an effort to encourage its suppliers to register their services within the UDDI directory.

As of this writing, Microsoft and IBM are the only two companies hosting registries. Both Hewlett-Packard and SAP have committed to hosting additional registries.

The registries are based on a single-master replication model. A business must choose a registry in which to maintain its information. All updates made to the directory will be replicated to all the other registries. Then the updated information can be queried from any registry.

The diagram below shows one user updating the UDDI business directory through a registrar and then another user accessing the updated information.

UDDI API

A UDDI registry is itself a Web service. It exposes a SOAP-based API for accessing and manipulating entries within the directory. Instead of maintaining data through a registrar, a developer can program directly against the API.

Version 1 of the UDDI API exposes about 30 methods for interacting with a registry, all of which behave synchronously. The following example shows how a UDDI request message is structured:

<?xml version="1.0" encoding="UTF-8" ?> <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">   <Body>     <find_business generic="1.0" xmlns="urn:uddi-org:api">       <name>MyTestBusiness</name>     </find_business >   </Body> </Envelope>

A UDDI message must meet some minimal requirements in order to be valid. (Some of those required elements are shown in bold in the previous example.) They are as follows:

  • The UDDI specification requires that the SOAP message be UTF-8 encoded.

  • The elements within the body of the UDDI document must be scoped within the UDDI API namespace. The UDDI API namespace is identified by the urn:uddi-org:api URI.

  • The request must contain a SOAPAction HTTP header whose value is an empty string. Any other value will be considered an error.

  • The version of the targeted API must be stated within the body of the message using the generic attribute.

Let's examine the last bullet point in more detail. As with any system, UDDI will continue to evolve. As enhancements are made, the API will have to be modified to expose the new functionality. As of this writing, version 2 of the API has completed the review process, has been ratified by the UDDI.org members, and is currently being implemented. To avoid breaking existing clients, the UDDI organization devised a versioning system to maintain some degree of backward compatibility.

The version of the API is referred to as its generic. Every UDDI message, including request and response messages, must indicate which generic it targets. Its generic attribute indicates the version number of the targeted API within the root element of the SOAP body.

The registry is responsible for supporting the current as well as the previous generic. The registry must also support generic version 1.

The UDDI API methods can be divided into two categories: the inquiry methods and the publishing methods. The inquiry methods allow you to search and browse the directory, and the publishing methods allow you to modify the contents of the directory. The messages for the inquiry methods have a root element in the SOAP body prefixed by find_ or get_. With a couple of exceptions, the messages for the publishing methods have a root element in the body of the SOAP message prefixed by save_ or delete_.

The technical specification for the UDDI API is published as a WSDL document as well as an XML Schema document. The XML Schema version is located at http://www.uddi.org/schema/2001/uddi_v1.xsd. The WSDL document for the Inquiry API is located at http://www.uddi.org/wsdl/inquire_v1.wsdl, and the WSDL document for the Publish API is at http://www.uddi.org/wsdl/publish_v1.wsdl. Table 9-1 describes the inquiry methods.

Table 9-1  UDDI API Inquiry Methods

Message

Description

find_binding

Searches for bindingTemplate entities that match a specified set of criteria

find_business

Searches for businessEntity entities that match a specified set of criteria

find_service

Searches for businessService entities that match a specified set of criteria

find_tModel

Searches for tModel entities that match a specified set of criteria

get_bindingDetail

Obtains one or more specific bindingTemplate entities

get_businessDetail

Obtains one or more specific businessEntity entities

get_businessDetailExt

Obtains one or more specific businessEntityExt entities from a registry that may support additional attributes

get_serviceDetail

Obtains one or more specific businessService entities

get_tModelDetail

Obtains one or more specific tModel entities

The find_ methods are for general searches, and the get_ methods are for obtaining detailed information about a particular record. Table 9-2 describes the publishing methods.

Table 9-2  UDDI API Publishing Methods

Message

Description

delete_binding

Deletes one or more specified bindingTemplate entities

delete_business

Deletes one or more specified businessEntity entities

delete_service

Deletes one or more specified businessService entities

delete_tModel

Deletes one or more specified tModel entities

discard_authToken

Invalidates the previously obtained authentication token

get_authToken

Obtains an authentication token for the user

get_registeredInfo

Obtains a list of businessInfo and tModelInfo entities for a particular user

save_binding

Saves one or more bindingTemplate entities

save_business

Saves one or more businessEntity entities

save_service

Saves one or more businessService entities

save_tModel

Saves one or more tModel entities

As I said before, the publishing methods are responsible for manipulating data within the directory. Both creates and updates are handled by the save_ messages. When a record is created using a save_ method, the registry generates a unique identifier. The unique identifier is then passed to subsequent save_ method calls to update the record. Each save_ message has a corresponding delete_ message for deletes.

The modifications made using the publishing methods must be done in a secure fashion. The UDDI specification states that all publishing messages must be exchanged between the client and the server over HTTPS. This prevents the contents of the message from being modified during transit.

A UDDI registry allows you to modify and delete only your own records, so you must include an authentication token with each request to prove your identity. This token is passed as part of the method signature of the save_ and delete_ methods.

You obtain an authentication token by passing your credentials to the get_authToken method. The implementation details of how a registry creates an authentication token are left up to the registry. The Microsoft registry uses Passport to authenticate its users. You pass a valid set of Passport credentials for a registered user, and the registry passes back a valid Passport token.

The methods defined by the UDDI API rely on a whole host of data structures. I discuss a number of them in the course of this chapter. You can find the entire list of data structures discussed in detail in the document titled “UDDI Programmer's API 1.0,” which is posted in various formats at www.uddi.org.

UDDI SDK

Microsoft provides a UDDI SDK for developing UDDI-enabled applications. The UDDI SDK includes both a .NET and a COM-based object model for simplifying interaction with the registry. It also includes a standalone UDDI registry for development purposes.

As of this writing, the UDDI SDK is still in beta and is distributed as a separate download. Microsoft currently does not have plans to ship the release to manufacture (RTM) version of the SDK in conjunction with the .NET Framework. Instead, it plans to ship the RTM version of the UDDI .NET object model on a release schedule separate from that of the .NET Framework.

UDDI .NET Object Model

The UDDI .NET object model includes a set of types that encapsulate the various methods and data structures defined by the UDDI specification. Unlike in other object models, in UDDI every method is represented by a corresponding .NET type. The type's name corresponds to the name of the method. To conform to the de facto standard naming convention, the .NET types are Pascal cased with the underscores removed. For example, the find_business method has a corresponding FindBusiness .NET type.

The .NET type exposes properties for setting parameters to be sent to the UDDI registry. Each .NET type also exposes a Send method to invoke its corresponding UDDI method. This might sound confusing, but it is fairly straightforward once you get the hang of it.

Similar mapping is provided for the entity datatypes defined by the UDDI API. For example, one of the datatypes I will introduce shortly is businessEntity. The .NET object model contains a corresponding BusinessEntity .NET type.

UDDI Developer Edition

Another useful tool that ships with the UDDI SDK is the UDDI Developer Edition, a registry you can install on your local machine. It supports all version 1 interfaces and can be an invaluable resource for testing.

The sample code presented in this chapter targets the locally installed UDDI Developer Edition registry. Here is the necessary information for interfacing with the registry:

  • Publish URI  http://localhost/publish.asmx

  • Inquiry URI  http://localhost/inquire.asmx

  • User Name  udditest

  • Password  Blank password

The UDDI SDK ships with a couple of sample applications that you can use to administer the UDDI registry. Only the source code is provided, so you must compile the applications before you can use them. The applications are

  • UDDIExplorer A simple UI for performing basic searches for businessEntity or tModel entries (described in the upcoming section)

  • UDDIPublish Migrates your entries from one UDDI registry to another

  • UDDIRegClean Removes all entries for a particular user

Because the UDDI Developer Edition supports only one user, UDDIRegClean is helpful for clearing all entries within the registry. UDDIPublish is useful when you want to copy the entries from a public registry and then perform testing against that data in a local environment.

UDDI Enterprise Server

Companies often need to discover services that are internal to the organization and not on the Internet. For example, a developer writing a reporting system for the sales department might be interested in learning what services the finance department exposes.

Practically every distributed object infrastructure provides a means of resolving the location of a particular component. The Service Control Manager provides this service for DCOM, and the Object Request Broker provides this service for CORBA. However, you can make a strong argument that UDDI is more robust and open than either the Service Control Manager or the Object Request Broker.

We need a corporate UDDI registry where internal services can be published. The UDDI Developer Edition was never intended to fill this role, so Windows .NET Server will feature native UDDI services that can be used to host a UDDI directory that is internal to a corporation.

UDDI services that ship with Windows .NET will have tight integration with the Active Directory as well as Windows security. When installed in an enterprise running Active Directory, the UDDI services will register themselves within Active Directory so that they can be easily discovered. The UDDI directory also supports integrated Windows security and can facilitate single sign-on via NT Challenge/Response. Finally, the UDDI services support role-based security and define three roles by default: Reader, Publisher, and Administrator. Check the MSDN UDDI Web site at http://msdn.microsoft.com/uddi for more information.

Registering the Purchaser

For Fabrikam to discover how to conduct electronic business with Contoso, Contoso must publish the necessary information to UDDI—including information about the Web services it exposes and the technical specifications they adhere to. In the process of registering Contoso, I will create and populate instances of six major UDDI datatypes:

  • businessEntity Defines the business itself

  • contact Contains information about a point of contact for the businessEntity

  • businessService Contains information about a collection of services

  • bindingTemplate Contains information about an entry point to a service

  • tModelInstanceInfo Serves as a cross-reference to a particular tModel

  • tModel Defines a particular specification for a service

Of the six types, the UDDI API provides methods for finding and creating four datatypes: businessEntity, businessService, bindingTemplate, and tModel. Instances of the other two datatypes are published using the save_ method of its parent. The following diagram shows how the datatypes relate to each other.

In the next section, I walk through the implementation of a simple console application that Contoso Motor Company can use to register itself in the UDDI directory.

Registering the Technical Specifications

First I need to register the technical specifications for the Invoice and the PurchaseOrder Web services. Note that UDDI is not responsible for holding the technical specification—it only provides a reference to the specification. You are responsible for making the specification available using some other means. This can be as simple as posting the specification on a Web site or publishing it within a repository such as BizTalk.org or RosettaNet.

The reference to the specification is contained within a tModel. A tModel is used to identify any unique abstract concept. For example, a tModel can serve as a reference pointer to a particular technical specification or it can be used to define a particular taxonomy. I will talk about how tModel entities are used to define taxonomies when I register the supplier.

Contoso needs to register two technical specifications, so it must define two tModel entities within the UDDI registry—one for how purchase orders will be issued to the supplier, and one for how the resulting invoice for goods shipped will be submitted back to Contoso.

How a specification is actually defined is irrelevant to UDDI because it is addressable via a URI. Because the tModel referencing the specification can be referenced by more than one service, the specification should not contain information specific to one instance of that service. Because both of Contoso's specifications define Web services, expressing the specifications in WSDL is a natural choice. In an effort to maximize reusability, you might want to ensure that the WSDL document does not contain information specific to a particular instance of the Web service.

Recall from Chapter 5 that a WSDL document contains one or more service sections. A service section contains port definitions that specify the endpoint of the Web service. Because a specification registered in UDDI should not contain information that is specific to one implementation, you should remove any service sections from the WSDL document before publishing it in UDDI.

Let's assume that both the Invoice and the PurchaseOrder WSDL documents were autogenerated by the ASP.NET runtime. In preparation for registering the Invoice and PurchaseOrder specifications with UDDI, I need to make a copy of the WSDL documents and remove the service sections from them. Then I need to publish them on Contoso's Web site so that they can be resolvable via a URI.

Here is the code to register tModel objects for the PurchaseOrder and Invoice Web services:

using System; using Microsoft.Uddi.Api; using Microsoft.Uddi; using Microsoft.Uddi.Business; using Microsoft.Uddi.ServiceType; using Microsoft.Uddi.Service; using Microsoft.Uddi.Binding; class Application {     static void Main(string[] args)     {         // Initialize the publisher parameters.         Publish.Url = "http://localhost/uddi/publish.asmx";         Publish.User = "udditest";         Publish.Password = "";

In the code, I reference various namespaces defined by the UDDI SDK. Note that you must add a reference to Microsoft.Uddi.Sdk.dll in order to reference the UDDI .NET types within your application.

Next I initialize the publisher parameters, including the URI, username, and password, by setting the associated static properties of the Publisher object. The static properties are accessed by all of the UDDI .NET types that encapsulate UDDI method calls.

Because the static properties of the Publish class are shared, you must alter the properties before you publish to another registry. This requirement can be challenging, especially in a multithreaded environment. In addition, it prevents the system from caching multiple HTTP 1.1 connections on your behalf. (Future releases of the SDK will provide better support for publishing to multiple registries.)

// **************************************************************** // * Register tModels for Invoice and PurchaseOrder Web services. // **************************************************************** SaveTModel saveTModel = new SaveTModel();

Next I create an instance of the SaveTModel class. This class lets you easily create a well-formed save_tModel message and submit it to the registry.

// Create tModel for the supplier invoice. saveTModel.TModels.Add();

The SaveTModel type exposes a TModels property that contains a collection of tModel entities to be saved to the registry. In the preceding code, I call the Add method to create a new tModel for the Invoice Web service.

Next I set properties of the tModel, including its name, a description, the overview document, and category information. The tModel name can be any combination of up to 128 characters. In this case, I use a URI syntax to ensure that the name is unique.

saveTModel.TModels[0].Name = "www-contoso-com:Invoice";

Next I give the tModel a user-friendly description. The description is accompanied by code that specifies the targeted language, in this case en for English. You can find a full list of codes at http://www.unicode.org/unicode/onlinedat/languages.html.

saveTModel.TModels[0].Descriptions.Add("en",  "Defines the interface for accepting invoices from suppliers.");

Whenever a UDDI datatype allows you to set a description, the datatype can contain more than one description element. However, only one description element for a particular language code should appear within an instance of a UDDI datatype, as shown here:

saveTModel.TModels[0].OverviewDoc.OverviewURL =  "http://www.contoso.com/Invoice.wsdl"; saveTModel.TModels[0].OverviewDoc.Descriptions.Add("en",  "The WSDL document describing the Invoice Web service.");

Next I specify the overview document. In this case, it is the URI to the edited version of the WSDL document that is automatically generated by the .NET platform.

// Categorize the tModel.  saveTModel.TModels[0].CategoryBag.Add("uddi-org:types", "wsdlSpec", "uuid:c1acf26d-9672-4404-9d70-39b756e62ab4");

Finally I add data to the tModel entity's category bag. The category bag is intended to contain metadata used to find specific tModel objects. For example, the Visual Studio .NET Add Web Reference Wizard will present only tModel entities that reference the wsdlSpec category.

A tModel can also contain an identifier bag. An identifier bag contains additional user-configurable identification numbers, which can be used as search parameters of the find_tModel method.

Three additional properties are exposed by the tModel object: Operator, AuthorizedName, and TModelKey. These properties are assigned by the registry when you publish a new tModel and therefore should be left blank when you create a new tModel.

The Operator property contains data indicating which registry holds the master copy of the tModel. The AuthorizedName property contains an identifier of the user that owns the record. The TModelKey property contains a unique identifier given to the record by the registry. Future versions of UDDI might allow you to provide your own more meaningful unique identifier.

Next I create a tModel for the PurchaseOrder Web service.

// Create tModel for the purchase order. saveTModel.TModels.Add(); saveTModel.TModels[1].Name = "www-contoso-com:PurchaseOrder"; saveTModel.TModels[1].Descriptions.Add("en",  "Defines the interface for sending invoices to suppliers."); saveTModel.TModels[1].OverviewDoc.OverviewURL =  "http://www.contoso.com/PurchaseOrder.wsdl"; saveTModel.TModels[1].OverviewDoc.Descriptions.Add("en", "The WSDL document describing the PurchaseOrder Web service exposed by the supplier."); saveTModel.TModels[1].CategoryBag.Add("uddi-org:types", "wsdlSpec", "uuid:c1acf26d-9672-4404-9d70-39b756e62ab4");

Recall that I need to describe how a supplier interacts with Contoso. This interaction involves both the PurchaseOrder and the Invoice Web services. However, up to this point the Web services are described in isolation. I need to define the workflow that incorporates both of these Web services.

tModel entities are not limited to specifying a particular Web service. You can use them to represent other specifications, such as transport protocols and even workflows. However, UDDI has not standardized how a tModel referencing a workflow should be published. One limiting factor is the current lack of a standard for defining workflow.

Microsoft currently supports XLANG for expressing workflow. XLANG is an XML dialect generated by a technology called Orchestration. Orchestration currently ships only with Microsoft BizTalk Server. However, this technology has broader appeal, especially for Web services.

If your business partners can consume XLANG, it is a good way to represent workflow. However, if you need broader reach, you can opt for something as simple as an HTML document that describes the workflow in written form. For this example, the following code creates a tModel that references an HTML document:

// Create tModel for the supplier workflow. saveTModel.TModels.Add(); saveTModel.TModels[2].Name = "www-contoso-com:PurchasingWorkflow"; saveTModel.TModels[2].Descriptions.Add("en", "Defines the workflow for  e-commerce transactions between the purchaser and its suppliers."); saveTModel.TModels[2].OverviewDoc.OverviewURL =  "http://www.contoso.com/PurchasingWorkflow.html"; saveTModel.TModels[2].OverviewDoc.Descriptions.Add("en", "This document describes the workflow encompassing the PurchaseOrder and Invoice Web  service.");

The preceding code defines a tModel that references the workflow describing how Contoso conducts a transaction with one of its suppliers. The details of the transaction are outlined in the PurchasingWorkflow.html document.

Once I define the tModel objects, the final step is to save them to the UDDI registry.

// Save the newly defined tModel entities. Console.WriteLine("The save_tModel message sent to the registry:"); Console.WriteLine(saveTModel.ToString()); TModelDetail savedTModelDetail = saveTModel.Send(); Console.WriteLine ("\nThe resulting tModelDetail message received from the registry:"); Console.WriteLine(savedTModelDetail.ToString());

Finally I use the Send method to submit the newly defined tModel entities to the registry and receive the resulting tModelDetail. The tModelDetail contains all the information about the tModel, including the properties populated by the UDDI registry. One of these properties, the unique identifier assigned to the Invoice tModel, will be referenced when I register Contoso's instance of this service.

The ToString method of the UDDI object model classes is overloaded to output the corresponding UDDI XML message. I use the ToString method to write both the save_tModel and the resulting tModelDetail messages to the console. The console output is shown here:

The save_tModel message sent to the registry: <?xml version="1.0"?> <save_tModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" generic="1.0"  xmlns="urn:uddi-org:api">   <tModel tModelKey="">     <name>www-contoso-com:Invoice</name>     <description xml:lang="en">Defines the interface for accepting invoices from     suppliers.</description>     <overviewDoc>       <description xml:lang="en">The WSDL document describing the Invoice Web        service.</description>       <overviewURL>http://www.contoso.com/Invoice.wsdl</overviewURL>     </overviewDoc>     <categoryBag>       <keyedReference tModelKey="uuid:c1acf26d-9672-4404-9d70-39b756e62ab4"        keyName="uddi-org:types" keyValue="wsdlSpec" />     </categoryBag>   </tModel>   <tModel tModelKey="">     <name>www-contoso-com:PurchaseOrder</name>     <description xml:lang="en">Defines the interface for sending a purchase      order to a supplier.</description>     <overviewDoc>       <description xml:lang="en">The WSDL document describing the PurchaseOrder       Web service exposed by the supplier.</description>       <overviewURL>http://www.contoso.com/PurchaseOrder.wsdl</overviewURL>     </overviewDoc>     <categoryBag>       <keyedReference tModelKey="uuid:c1acf26d-9672-4404-9d70-39b756e62ab4"        keyName="uddi-org:types" keyValue="wsdlSpec" />     </categoryBag>   </tModel>   <tModel tModelKey="">     <name>www-contoso-com:PurchasingWorkflow</name>     <description xml:lang="en">Defines the workflow for e-commerce transactions      between the purchaser and its suppliers.</description>     <overviewDoc>       <description xml:lang="en">This document describes the workflow        encompassing the PurchaseOrder and Invoice Web service.</description>       <overviewURL>http://www.contoso.com/PurchasingWorkflow.html</overviewURL>     </overviewDoc>   </tModel> </save_tModel> The resulting tModelDetail message received from the registry: <?xml version="1.0"?> <tModelDetail xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" generic="1.0"  operator="Microsoft UDDI Developer Edition Test Operator" truncated="false" xmlns="urn:uddi-org:api">   <tModel tModelKey="uuid:a89493a6-d0d0-415b-8c41-a34caf8c6c43"    operator="Microsoft UDDI Developer Edition Test Operator">     <name>www-contoso-com:Invoice</name>     <description xml:lang="en">Defines the interface for accepting invoices from     suppliers.</description>     <overviewDoc>       <description xml:lang="en">The WSDL document describing the Invoice Web        service.</description>       <overviewURL>http://www.contoso.com/Invoice.wsdl</overviewURL>     </overviewDoc>     <categoryBag>       <keyedReference tModelKey="uuid:c1acf26d-9672-4404-9d70-39b756e62ab4"        keyName="uddi-org:types" keyValue="wsdlSpec" />     </categoryBag>   </tModel>   <tModel tModelKey="uuid:2a1109ff-5d31-4df1-86f6-b8fcff797030"    operator="Microsoft UDDI Developer Edition Test Operator">     <name>www-contoso-com:PurchaseOrder</name>     <description xml:lang="en">Defines the interface for sending a purchase      order to a supplier.</description>     <overviewDoc>       <description xml:lang="en">The WSDL document describing the PurchaseOrder       Web service exposed by the supplier.</description>       <overviewURL>http://www.contoso.com/PurchaseOrder.wsdl</overviewURL>     </overviewDoc>     <categoryBag>       <keyedReference tModelKey="uuid:c1acf26d-9672-4404-9d70-39b756e62ab4"        keyName="uddi-org:types" keyValue="wsdlSpec" />     </categoryBag>   </tModel>   <tModel tModelKey="uuid:b31cff85-8b1b-4502-bce1-92229f579238"    operator="Microsoft UDDI Developer Edition Test Operator">     <name>www-contoso-com:PurchasingWorkflow</name>     <description xml:lang="en">Defines the workflow for e-commerce transactions      between the purchaser and its suppliers.</description>     <overviewDoc>       <description xml:lang="en">This document describes the workflow        encompassing the PurchaseOrder and Invoice Web service.</description>       <overviewURL>http://www.contoso.com/PurchasingWorkflow.html</overviewURL>     </overviewDoc>   </tModel> </tModelDetail>

Registering Contoso Motor Company

Now that I have published the technical specifications necessary to facilitate communication between a purchaser and its suppliers, the next step is to register the purchaser. The UDDI entry for Contoso Motor Company will contain basic contact information as well as information about the Invoice Web service it exposes.

Information relating to a specific company is contained within a business Entity datatype. This includes general information such as the company's address and phone number as well as technical information about the Web services it exposes.

The following code creates a businessEntity and publishes it to the registry using the save_business method:

// **************************************************************** // * Register businessEntity for Contoso Motor Company. // **************************************************************** SaveBusiness saveBusiness = new SaveBusiness(); BusinessEntity contoso = new BusinessEntity(); saveBusiness.BusinessEntities.Add(contoso); contoso.Name = "Contoso Motor Company"; contoso.Descriptions.Add("en",  "Striving to make the world a better place. (TM)");

I first create an object of type BusinessEntity and set its name and description. Unlike the previous code that created a tModel, I explicitly create an instance of the BusinessEntity class instead of implicitly creating one using the SaveBusiness.Add method. I did this to avoid requiring 24-inch-wide paper stock to print this section.

Because the businessEntity contains such a wide array of information, it defines a fairly deep hierarchy of nested datatypes. If I were to access the properties of the nested objects by navigating through an object of type SaveBusiness, my code would quickly become unwieldy.

Next I create a contact record and add it to the businessEntity. The PersonName property contains the contact's full name, and the UseType property contains an optional free-form text field that identifies the type of contact.

// Add primary contact information to the businessEntity. Contact primaryContact = new Contact(); businessEntity.Contacts.Add(primaryContact); primaryContact.PersonName = "James Smith"; primaryContact.UseType = "primary contact"; primaryContact.Descriptions.Add("en", "Primary Contact"); primaryContact.Phones.Add("800-555-0123", "main"); primaryContact.Emails.Add("james@contoso.com", "main"); primaryContact.Addresses.Add("1", "office"); primaryContact.Addresses[0].AddressLines.Add("P.O. Box 1234"); primaryContact.Addresses[0].AddressLines.Add("Dearborn, MI 56789"); businessEntity.Contacts.Add(primaryContact);

I set a similar UseType property for the phone number, e-mail address, and physical address. However, note that the UseType field of the phone number and e-mail address is not optional if more than one phone number or e-mail address is listed.

Note that the order of the address lines is significant. The registry will always return the address lines in the order in which they were originally saved.

Next I add a new businessService that describes a collection of Web services that enable Contoso's SCM process. A businessService describes a set of Web services used to solve a particular business problem. In this case, the businessService contains a single entry for the Invoice Web service.

// Add a businessService for the Web services related to SCM. BusinessService scmService = new BusinessService(); contoso.BusinessServices.Add(scmService); scmService.Name = "Supply Chain Management Web Services"; scmService.Descriptions.Add("en",  "Web services for conducting e-commerce with suppliers.");

The UDDI API also provides the save_businessService method for directly publishing a new businessService. This is encapsulated by the SaveBusinessService type in the .NET UDDI SDK.

If you use the SaveBusinessService type to create a new businessService, the BusinessKey property must point to a valid businessEntity. However, in this case the new businessService is nested within its parent businessEntity and can therefore have a blank BusinessKey property.

Finally, the businessService contains a category bag. Similar to the category bag exposed by the businessEntity, it categorizes a collection of services exposed by the businessService, as shown here:

// Add a bindingTemplate for the Invoice Web service. BindingTemplate invoiceBinding = new BindingTemplate(); scmService.BindingTemplates.Add(invoiceBinding); invoiceBinding.Descriptions.Add("en", "This template describes the technical  specifications you must comply with in order to submit invoices to Contoso."); invoiceBinding.AccessPoint.Text = "http://contoso.com/Invoice.asmx"; invoiceBinding.AccessPoint.URLType = URLTypeEnum.Http;

Next I add a bindingTemplate for the Invoice Web service. The bindingTemplate defines a specific endpoint for a Web service. The URI of the endpoint is specified by the AccessPoint property.

Instead of specifying an endpoint, a bindingTemplate can reference another bindingTemplate. You can accomplish this by setting the HostingRedirector property equal to the UUID of another binding template. If the HostingRedirector property is set, the client must obtain the URI of the endpoint from the referenced bindingTemplate.

As with the businessService, you can use an instance of the .NET UDDI SDK SaveBindingTemplate type to publish a new bindingTemplate to the registry. If you do this, the ServiceKey property must contain a valid reference to its parent businessService, as shown here:

// Add tModelInstanceInfo for Invoice. TModelInstanceInfo invoice = new TModelInstanceInfo(); invoiceBinding.TModelInstanceDetail.TModelInstanceInfos.Add(invoice); invoice.TModelKey = savedTModelDetail.TModels[0].TModelKey; invoice.Descriptions.Add("en",  "The submitted invoice must be a result of receiving a PO from Contoso."); invoice.InstanceDetail.Descriptions.Add("en",  "The WSDL document for this instance of the Invoice Web service."); invoice.InstanceDetail.OverviewDoc.OverviewURL =  "http://contoso.com/Invoice.asmx?wsdl"; invoice.InstanceDetail.OverviewDoc.Descriptions.Add("en", "Some description.");

Next I add a tModelInstanceInfo to the bindingTemplate. The tModelInstanceInfo references a particular tModel in which the endpoint described by the parent bindingTemplate claims compliance.

Recall that the WSDL document referenced by the Invoice Web service tModel does not contain information specific to any one instance of a Web service. Many toolsets, including the ones provided by .NET, require a complete WSDL document in order to generate a fully functional proxy. Therefore, the tModelInstanceInfo datatype contains a reference to the WSDL document that imports the interface definitions and defines the implementation-specific service element.

In this case, I referenced the WSDL automatically generated by ASP.NET. The WSDL document imports the original interface definitions using the WebBindingService attribute. (See Chapter 5 for more information.)

The tModelInstanceInfo contains a reference to a document that describes the specifics about the implementation of a particular tModel. The documentation might be for programmatic consumption—a WSDL document, for example. Or it might have a more user-friendly form, such as an HTML or a Word document. The document can be used to describe instance-specific details such as security and account registration.

The UDDI organization is currently defining best practices regarding the use of the tModelInstanceInfo. Check the UDDI Best Practices Web site at http://www.uddi.org/bestpractices.html for more information.

Next I add another tModelInstance that references the workflow.

// Add tModelInstanceInfo for SupplierWorkflow. TModelInstanceInfo workflow = new TModelInstanceInfo(); invoiceBinding.TModelInstanceDetail.TModelInstanceInfos.Add(workflow); workflow.TModelKey = savedTModelDetail.TModels[2].TModelKey; workflow.Descriptions.Add("en", "This document describes the workflow  encompassing the PurchaseOrder and Invoice Web service.");

For this tModelInstanceInfo, I have decided to not publish information about the tModel that is specific to the implementation, so I don't include a tModelInstanceInfo.

Console.WriteLine("The save_Business message sent to the registry:"); Console.WriteLine(saveBusiness.ToString()); BusinessDetail businessDetail = saveBusiness.Send(); Console.WriteLine ("The resulting businessDetail message received from the registry:"); Console.WriteLine(businessDetail.ToString());

Finally I publish the businessEntity to the UDDI registry by calling the Send method of the saveBusiness object. As in the tModel example, I output the messages sent between the client and the registry to the console. Here is the resulting message sent to the UDDI registry and the response from the registry:

The save_Business message sent to the registry: <?xml version="1.0"?> <save_business xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" generic="1.0"  xmlns="urn:uddi-org:api">   <businessEntity businessKey="">     <name>Contoso Motor Company</name>     <description xml:lang="en">Striving to make the world a better place. (TM)     </description>     <contacts>       <contact useType="primary contact">         <description xml:lang="en">Primary Contact</description>         <personName>James Smith</personName>         <phone useType="main">800-555-0123</phone>         <email useType="main">james@contoso.com</email>         <address sortCode="1" useType="office">           <addressLine>P.O. Box 1234</addressLine>           <addressLine>Dearborn, MI 56789</addressLine>         </address>       </contact>     </contacts>     <businessServices>       <businessService serviceKey="" businessKey="">         <name>Purchasing Web Services</name>         <description xml:lang="en">       Web services for conducting purchasing related transactions.</description>         <bindingTemplates>           <bindingTemplate serviceKey="" bindingKey="">             <description xml:lang="en">             The Web service for submitting invoices to Contoso.</description>             <accessPoint URLType="http">             http://contoso.com/Invoice.asmx</accessPoint>             <tModelInstanceDetails>               <tModelInstanceInfo tModelKey=               "uuid:a89493a6-d0d0-415b-8c41-a34caf8c6c43">               <description xml:lang="en">The submitted invoice must be a result               of receiving a PO from Contoso                (www-contoso-com:SupplierInvoice).</description>                 <instanceDetails>                   <description xml:lang="en">The WSDL document for this                    instance of the Invoice Web service.</description>                   <overviewDoc>                     <description xml:lang="en">Some description.</description>                     <overviewURL>http://contoso.com/Invoice.asmx?wsdl                     </overviewURL>                   </overviewDoc>                 </instanceDetails>               </tModelInstanceInfo>               <tModelInstanceInfo tModelKey=               "uuid:b31cff85-8b1b-4502-bce1-92229f579238">               <description xml:lang="en">This document describes the workflow                encompassing the PurchaseOrder and Invoice Web service.               </description>                 <instanceDetails>                   <overviewDoc />                 </instanceDetails>               </tModelInstanceInfo>             </tModelInstanceDetails>           </bindingTemplate>         </bindingTemplates>       </businessService>     </businessServices>   </businessEntity> </save_business> The resulting businessDetail message received from the registry: <?xml version="1.0"?> <businessDetail xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" generic="1.0"  operator="Microsoft UDDI Developer Edition Test Operator" truncated="false" xmlns="urn:uddi-org:api">   <businessEntity businessKey="ac5782d8-d69b-4402-9262-caf189536c89"    operator="Microsoft UDDI Developer Edition Test Operator">     <discoveryURLs>       <discoveryURL useType="businessEntity">       http://localhost/uddi/discovery.ashx?businessKey=       ac5782d8-d69b-4402-9262-caf189536c89</discoveryURL>     </discoveryURLs>     <name>Contoso Motor Company</name>     <description xml:lang="en">Striving to make the world a better place. (TM)     </description>     <contacts>       <contact useType="primary contact">         <description xml:lang="en">Primary Contact</description>         <personName>James Smith</personName>         <phone useType="main">800-555-0123</phone>         <email useType="main">james@contoso.com</email>         <address sortCode="1" useType="office">           <addressLine>P.O. Box 1234</addressLine>           <addressLine>Dearborn, MI 56789</addressLine>         </address>       </contact>     </contacts>     <businessServices>       <businessService serviceKey="e5ae9f03-585b-4fee-8a89-5d29f0079b02"        businessKey="ac5782d8-d69b-4402-9262-caf189536c89">         <name>Purchasing Web Services</name>         <description xml:lang="en">Web services for conducting purchasing          related transactions.</description>         <bindingTemplates>           <bindingTemplate serviceKey="e5ae9f03-585b-4fee-8a89-5d29f0079b02"            bindingKey="f9cfeb33-4b83-4cc5-9cd4-d332160530c0">             <description xml:lang="en">             The Web service for submitting invoices to Contoso.</description>             <accessPoint URLType="http">             http://contoso.com/Invoice.asmx</accessPoint>             <tModelInstanceDetails>               <tModelInstanceInfo tModelKey=               "uuid:a89493a6-d0d0-415b-8c41-a34caf8c6c43">                <description xml:lang="en">The submitted invoice must be a result               of receiving a PO from Contoso                (www-contoso-com:SupplierInvoice).</description>                 <instanceDetails>                   <description xml:lang="en">The WSDL document for this                    instance of the Invoice Web service.</description>                   <overviewDoc>                     <description xml:lang="en">Some description.</description>                     <overviewURL>http://contoso.com/Invoice.asmx?wsdl                     </overviewURL>                   </overviewDoc>                 </instanceDetails>               </tModelInstanceInfo>               <tModelInstanceInfo tModelKey=               "uuid:b31cff85-8b1b-4502-bce1-92229f579238">                 <description xml:lang="en">This document describes the workflow                 encompassing the PurchaseOrder and Invoice Web service.                 </description>                 <instanceDetails>                   <overviewDoc />                 </instanceDetails>               </tModelInstanceInfo>             </tModelInstanceDetails>           </bindingTemplate>         </bindingTemplates>       </businessService>     </businessServices>   </businessEntity> </businessDetail>

Searching for Contoso Motor Company

Now that Contoso Motor Company is registered, a supplier can obtain information about the registered services by querying the UDDI registry. To facilitate this, the UDDI API exposes a set of get_ and find_ methods. The find_ methods are used to perform general queries. The information returned is typically enough to display a meaningful result set to the user. You can then use the get_ methods to retrieve the full information about a particular entry.

The following example retrieves the businessDetail entry listed in the previous section:

// Search for all businesses that have the name Contoso Motor Company. FindBusiness findBusiness  = new FindBusiness(); findBusiness.Name = "Contoso Motor Company "; BusinessList businessList = findBusiness.Send(); // Get the businessDetail for the first entry in the result set. GetBusinessDetail getBusinessDetail = new GetBusinessDetail(); getBusinessDetail.BusinessKeys.Add(businessList.BusinessInfos[0].BusinessKey); BusinessDetail businessDetail = getBusinessDetail.Send(); Console.WriteLine ("The resulting businessDetail message received from the registry:"); Console.WriteLine(businessDetail.ToString());

I first search for all businessEntity entries with the name Contoso Motor Company. By default, UDDI performs leftmost name matching and is not case sensitive. For example, the search strings CONTOSO, Contoso Motor, and Contoso Motor Co will all locate the entry I published in the previous section.

You can modify the behavior of a query by specifying a qualifier within the FindBusiness.FindQualifiers property. Table 9-3 describes the find qualifiers that a UDDI registry must support. In addition, individual registries can support an extended set of qualifiers.

Table 9-3  UDDI Registry Find Qualifiers

Value

Description

exactNameMatch

Specifies that the entire string must match the name. By default, it is case insensitive.

caseSensitiveMatch

Specifies that case is relevant within the specified search string.

sortByNameAsc

Specifies that the result set should be sorted alphabetically in ascending order.

sortByNameDesc

Specifies that the result set should be sorted alphabetically in descending order.

sortByDateAsc

Specifies that the result set should be sorted by the date last updated in ascending order.

sortByDateDesc

Specifies that the result set should be sorted by the date last updated in descending order.

Obviously, sortByNameAsc and sortByNameDesc are mutually exclusive, as are sortByDateAsc and sortByDateDesc. However, any other combination of the find qualifiers is allowed. If more than one find qualifier is specified, the following order of precedence is applied:

  1. exactNameMatch and caseSensitiveMatch

  2. sortByNameAsc and sortByNameDesc

  3. sortByDateAsc and sortByDateDesc

Once I obtain my search results, I use the getBusinessDetail object to get the details of the first record returned in my search results. The businessDetail returned contains the information necessary for a supplier to establish an e-business relationship with Contoso. Items of importance include the businessEntity UUID, the bindingTemplate access point, and the UUIDs for the tModel objects.

Registering the Supplier

When a supplier registers itself in the UDDI directory, registering just the name, address, and phone number is not sufficient. It must register in such a way that Contoso and other potential customers can find it.

UDDI provides a way to categorize entries within the directory using well-known taxonomies. The supported taxonomies include the North American Industry Classification System (NAICS - 1997), the Universal Standard Products and Services Codes (UNSPSC - 3.01), the Standard Industrial Classification (SIC - 1987), and the GeoWeb geographic classification (August 2000).

I used a taxonomy earlier in this chapter when I specified the www-contoso-com:Invoice and www-contoso-com:PurchaseOrder tModel entities. Here is the portion of the code I used to register the tModel entities:

saveTModel.TModels[0].Name = "www-contoso-com:Invoice"; // Set additional properties... saveTModel.TModels[0].CategoryBag.Add("uddi-org:types", "wsdlSpec", "uuid:c1acf26d-9672-4404-9d70-39b756e62ab4");

The preceding code uses the UDDI Type Taxonomy to categorize the tModel as one that references a WSDL document. A taxonomy is itself defined by a tModel definition. This is the other primary use of tModel entities besides representing a technical specification.

In the preceding example, the third parameter of the CategoryBag.Add method references the tModel that defines the UDDI Type Taxonomy. The UDDI Type Taxonomy is used to categorize the type of data a tModel references. The taxonomy is hierarchical in nature, as shown in the following figure. Table 9-4 lists the valid values defined by the taxonomy.

Table 9-4  UDDI Type Taxonomy Values

ID

Description

tModel

The root branch of the taxonomy hierarchy. End-user categorization on this value is not allowed.

identifier

Specifies that the tModel represents a taxonomy of unique identifiers. The DUNS number uniquely identifies a company and is an example of an identifier tModel.

namespace

Specifies that the tModel represents a scoping constraint. This value is synonymous with XML namespaces and is used to avoid naming collisions.

categorization

Specifies that the tModel represents a method of categorization. The NAICS and UNSPSC—and even the UDDI Type Taxonomy—are all examples of categorization tModel entities.

specification

Specifies that the tModel references a contract that defines the interaction with a particular service. COM and RPC services are examples of specification tModel entities.

xmlSpec

Specifies that the tModel references a contract that defines the interaction with a particular service using XML. Examples of xmlSpec tModel entities include a DTD and an XML Schema schema.

soapSpec

Specifies that the tModel references a contract that defines an interaction with a particular service using SOAP. The schema for the Inquire UDDI API is an example of a soapSpec tModel.

wsdlSpec

Specifies that the tModel references a WSDL document that defines an interaction with a particular service. The www-contoso-com:Invoice tModel is an example of a wsdlSpec tModel.

protocol

Specifies that the tModel references a particular protocol for interacting with a particular service.

transport

Specifies that the tModel references a particular transport protocol for interacting with a particular service. HTTP and FTP are examples of transport tModel entities.

signatureComponent

Specifies that the tModel does not represent the complete specification for a Web service. An example would be an individual step in a business process.

You can create your own taxonomies by creating a tModel that contains a categorization entry in its category property bag. However, to help ensure that potential purchasers can find Fabrikam when they are looking for a wing nuts manufacturer, I use a taxonomy that is core to UDDI. (The taxonomies that are essential to UDDI are listed at http://www.uddi.org/taxonomies/Core_Taxonomy_OverviewDoc.htm.)

Specifically, I categorize Fabrikam Wing Nuts using the UNSPSC. The UNSPSC is defined by the Electronic Commerce Code Management Association (ECCMA) and can be browsed at http://eccma.org/unspsc/browse/.

The following console application registers Fabrikam Wing Nuts in the UDDI directory:

using System; using Microsoft.Uddi.Api; using Microsoft.Uddi; using Microsoft.Uddi.Business; using Microsoft.Uddi.ServiceType; using Microsoft.Uddi.Service; using Microsoft.Uddi.Binding; class Application {     static void Main(string[] args)     {         // Initialize the publisher parameters.         Publish.Url = "http://localhost/uddi/publish.asmx";         Publish.User = "udditest";         Publish.Password = "";         // Create a new businessEntity.         SaveBusiness saveBusiness = new SaveBusiness();         BusinessEntity fabrikam = new BusinessEntity();         saveBusiness.BusinessEntities.Add(fabrikam);         fabrikam.Name = "Fabrikam Wing Nuts";         fabrikam.Descriptions.Add("", "Just a bunch of wing nuts.");         // Add the UNSPSC code for wing nut manufacturer.         fabrikam.CategoryBag.Add("unspsc-org:unspsc", "31.16.17.17.00",                  "uuid:CD153257-086A-4237-B336-6BDCBDCC6634");     // Contact information...

The preceding code creates a businessEntity for Fabrikam Wing Nuts and categorizes it using the UNSPSC taxonomy. The code for wing nut manufacturers is 31.16.17.17.00. (Yes, there actually is a code defined for wing nut manufacturers.) If Fabrikam decides to diversify its product line, it can add more entries to the category property bag.

        // Add a businessService for the Web services          // related to supply chain management.         BusinessService scmService = new BusinessService();         fabrikam.BusinessServices.Add(scmService);         scmService.Name = "Supply Chain Management Web Service";         scmService.Descriptions.Add("",          "Web services for conducting e-commerce with suppliers.");         // Add the binding template for the PurchaseOrder Web service.         BindingTemplate purchaseOrderBinding = new BindingTemplate();         scmService.BindingTemplates.Add(purchaseOrderBinding);         purchaseOrderBinding.Descriptions.Add("",          "The Web service for submitting purchase orders to Fabrikam Wing Nuts.");         purchaseOrderBinding.AccessPoint.Text =          "http://fabrikam.com/PurchaseOrder.asmx";         purchaseOrderBinding.AccessPoint.URLType = URLTypeEnum.Http;         // Add a reference to the www-contoso-com:PurchaseOrder tModel.         TModelInstanceInfo purchaseOrder = new TModelInstanceInfo();         purchaseOrderBinding.TModelInstanceDetail.TModelInstanceInfos.Add         (purchaseOrder);         purchaseOrder.TModelKey = "uuid:2a1109ff-5d31-4df1-86f6-b8fcff797030";         Console.WriteLine("The save_Business message sent to the registry:");         Console.WriteLine(saveBusiness.ToString());         BusinessDetail businessDetail = saveBusiness.Send();         Console.WriteLine         ("The resulting businessDetail message received from the registry:");         Console.WriteLine(businessDetail.ToString());     } }

I register the Invoice Web services that are compliant with Contoso's www-contoso-com:PurchaseOrder tModel, and then I save the businessEntity to the registry.

Searching for the Supplier

When Contoso Motor Company needs to replenish its supply of wing nuts, it can search the UDDI directory for potential suppliers. The following code searches the UDDI directory for suppliers.

Inquire.Url = "http://test.uddi.microsoft.com/inquire"; FindBusiness findBusiness = new FindBusiness(); findBusiness.CategoryBag.Add("unspsc-org:unspsc", "31.16.17.17.00", "uuid:CD153257-086A-4237-B336-6BDCBDCC6634"); findBusiness.TModelKeys.Add("uuid:2a1109ff-5d31-4df1-86f6-b8fcff797030"); BusinessList businessList = findBusiness.Send(); Console.WriteLine(businessList);

The preceding code searches for all businessEntity entries that are categorized as wing nut manufacturers and also expose the PurchaseOrder Web service. Because Fabrikam meets these criteria, it will be included in the resulting businessList.

The ability to search for potential suppliers in a centralized directory offers a couple of advantages. First, suppose Contoso already has an established relationship with another wing nut supplier. If, for some reason, this supplier cannot accommodate Contoso's orders, Contoso can search the directory for other potential suppliers.

Another advantage of a centralized directory is that companies other than Contoso can locate Fabrikam in the UDDI directory. For example, if Billy's Rocking Horse Manufacturing is putting together a new line that requires wing nuts, it can locate Fabrikam by performing a search of the UDDI directory.

Visual Studio .NET Integration

Visual Studio .NET supports UDDI. The two primary points of integration are the Visual Studio .NET Start page and the Add Web Reference Wizard.

The Visual Studio .NET Start page lets you register Web services as well as search for Web services registered in the UDDI directory. This functionality is available through the XML Web Services page, which serves as a portal to a registrar customized for Visual Studio .NET.

This Web page is hosted on the Internet, so it is subject to change. As of this writing, it has three tabs: Getting Started, Find A Service, and Register A Service. The latter two tabs are used to register and locate Web services in the Microsoft test and production UDDI registry.

The Find A Service tab presents a simple search screen for finding Web services that have been categorized using the VSCATEGORY taxonomy. You can easily add each resulting entry to the current project by clicking on the link provided.

The Register A Service tab provides a simple three-step UI for registering a Web service. On the first screen, you log in with your Passport credentials. The next screen gives you the option to publish against the Microsoft test or production registry. Here is the final screen, where you enter information about the Web service:

The information provided is used to create a businessService with an associated bindingTemplate. The Web Service Name and Description fields set the name and description of the businessService, respectively. The .asmx URL, .wsdl URL, and Service Category are used to set the appropriate properties on the bindingTemplate. The Visual Studio .NET registrar also registers a tModel on your behalf.

The following is the businessService entity that is created as a result of the above registration:

<businessService serviceKey="3a4d24a1-9722-4499-87bb-ed7cb39d01a5"  businessKey="c2a5e253-a10d-431c-a167-016d057f8890">   <name>Test Web Service</name>   <description xml:lang="en">This is only a test.</description>   <bindingTemplates>     <bindingTemplate serviceKey="3a4d24a1-9722-4499-87bb-ed7cb39d01a5"      bindingKey="bcbdd1a4-3605-4950-bc83-46ddb17e51dc">     <description xml:lang="en">This is only a test.</description>     <accessPoint URLType="http">http://test/test.asmx</accessPoint>     <tModelInstanceDetails>       <tModelInstanceInfo tModelKey="uuid:e4fe05d6-2691-430a-bbfd-81d6e5491b91">       <description xml:lang="en">WSDL Web Service Interface (Added by VS)       </description>       <instanceDetails>         <description xml:lang="en">WSDL Web Service Interface (Added by VS)         </description>         <overviewDoc>         <overviewURL>http://test/test.asmx?wsdl</overviewURL>         </overviewDoc>       </instanceDetails>       </tModelInstanceInfo>     </tModelInstanceDetails>     </bindingTemplate>   </bindingTemplates>   <categoryBag>     <keyedReference tModelKey="uuid:4c1f2e1f-4b7c-44eb-9b87-6e7d80f82b3e"      keyName="VSCATEGORY" keyValue="14" />   </categoryBag> </businessService>

In addition to using the Find A Service tab on the Visual Studio .NET Start page, you can also search for Web services registered in UDDI using the Add Web Reference Wizard. The wizard allows you to search for all Web services published by a particular businessEntity. The following is the result of a search for all Web services published by the GotDotNet businessEntity:

Only entries that reference tModel objects in the wsdlSpec category are listed. To add a reference to a Web service, click on the link to its WSDL interface and then click the Add Reference button.



Building XML Web Services for the Microsoft  .NET Platform
Building XML Web Services for the Microsoft .NET Platform
ISBN: 0735614067
EAN: 2147483647
Year: 2002
Pages: 94
Authors: Scott Short

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net