Keep Web Service Calls Current

Use the UDDI invocation pattern to help your apps find Web Services — even when those Web Services move.

asp:cover story

Language: VB | C#

Technologies: Web Services | UDDI

 

Keep Web Service Calls Current

Use the UDDI invocation pattern to help your apps find Web Services - even when those Web Services move.

 

By Yasser Shohoud

 

One of the big draws of .NET is that your applications can call upon Web Services all over the Web, which gives you easy, distributed computing. And that's great, as long as all the Web Services your application uses are where you expect them to be.

 

But what if a Web Service moves? That's when you need to use the Universal Description, Discovery, and Integration (UDDI) invocation pattern. UDDI is a directory of Web Services that can be searched programmatically through a standard Web Service interface. You can program your Web Service clients to search UDDI and locate Web Services at run time dynamically. This capability leads to a useful scenario known as the invocation pattern. The ability to locate Web Services dynamically at run time is one UDDI's most useful features. Figure 1 shows a client application that implements the UDDI invocation pattern.

 


Figure 1. This sequence shows interaction between the client, UDDI, and the Web Service in the UDDI invocation pattern. The client attempts to invoke a service that has moved. When this attempt fails, the client queries UDDI to get the current service location and then invokes the service at the new location.

 

If a Web Service moves to a new location, clients invoking that service get an HTTP error such as 404 Not Found. If the service owner has updated UDDI to reflect the change in location, however, a client that implements the UDDI invocation pattern can query UDDI for the service's current location. The client proceeds to call the service at this new location and resumes normal processing.

 

In this article, you'll learn to implement the UDDI invocation pattern in a reusable component you can use in Web and Windows client applications.

 

Create the Web Service

To demonstrate the invocation pattern, you can create a simple Web Service with one method that returns the current date and time on the server:

 

Imports System.Web.Services

Public Class ServerTime

     _

      Public Function GetTime() As DateTime

        Return System.DateTime.Now

    End Function

End Class

 

To implement the invocation pattern, you must register this service with UDDI. If you don't have a UDDI login already, you need to register at the Microsoft UDDI version 2 site (http://uddi.rte.microsoft.com). After you've obtained a UDDI login, you need to sign in to UDDI and create a new provider, which is a business entity or company that exposes Web Services. Once you've registered a provider, you can register your Web Service with UDDI and point it to the current location of this Web Service; for example, http://yourServerName/ServerTime.asmx.

 

Registering a Web Service with UDDI can be a little confusing at first. EraServer.com provides a registration service named qUDDI (http://qUddi.EraServer.com), which is a simple alternative to using the UDDI interface. If you use qUDDI to register your service for this article, be sure to use the Business qUDDI at http://quddi.eraserver.com/business.aspx because it lets you register your service under your own provider. You'll need this later when you change the Web Service location.

 

Use a simple Web form named TimeClient.aspx to call the ServerTime Web Service. (See the Download box at the beginning of the article for details about downloading this and other files used in the article.) If you open this file, you'll see a script block at the top containing the Web Service's proxy code. I generated this proxy using wsdl.exe with this command-line statement:

 

wsdl.exe /l:VB /out:Proxy.vb http://localhost/demos/ws/TimeWS/ServerTime.asmx?wsdl

 

This command generates proxy code to a file named proxy.vb. Normally, you would compile this proxy and then create a client that references the compiled proxy assembly. In this instance, however, I copied the code out of the proxy file and pasted it into the client's server script block. This simplifies deployment because all the code needed to call the Web Service is in one file, TimeClient.aspx.

 

The user interface for this client consists of a button and a literal control for outputting results, as shown in Figure 2.

 


Figure 2. Here is a simple client for the ServerTime Web Service. The client calls the GetTime method and displays the returned time in a Web form. If the call fails, the client will attempt to recover by using the invocation pattern and UDDI.

 

When the user clicks on the Get Time button, the VB code in Figure 3 instantiates and calls the ServerTime Web Service. If an error occurs, the code simply reports the exception to the user.

 

Figure 3. This code calls the ServerTime Web Service. The code first instantiates a ServerTime object, which acts as the Web Service proxy. A Try...Catch block wraps the call to GetTime, which returns a DateTime structure. The returned structure is displayed along with the Web Service's location.

 

Clicking on Get Time displays the server time and the URL of the Web Service (see Figure 2). If you rename the Web Service asmx file or move it to a different location, the client will report an error as shown in Figure 4.

 


Figure 4. Renaming ServerTime.asmx causes the client to report a 404 error.

 

Implement the Invocation Pattern

Now you're ready to leverage the UDDI invocation pattern to make this client find and invoke the new service URL automatically. To implement the invocation pattern in a reusable component, I created a new class library project named InvocationPattern and added to it a class named InvocationPattern. This class exposes two methods: IsRecoverable and GetCurrentUrl. IsRecoverable takes in a System.Exception object and returns True if it is the kind of exception that might arise when the Web Service is moved. For example, if the exception is because of an invalid SOAP request or response message, the UDDI invocation pattern will not help, so IsRecoverable returns False. GetCurrentUrl uses the UDDI version 2 SDK to invoke the UDDI GetBindingDetail API.

 

In order to invoke the GetBindingDetail API, you must have a binding key, which is the unique identifier of the binding whose details you want to retrieve. You can find a binding key by searching UDDI for the service you registered (using your service name) and clicking on the binding node (the icon with three computers in a network) in the resulting explorer tree view. Figure 5 shows the binding key on the right.

 


Figure 5. You obtain the binding key by searching UDDI. Begin by searching for your service by name. Then, expand the service node in the tree view and expand the child binding node. The binding key appears on the right with the service's URL.

 

Figure 6 shows the GetCurrentUrl method (written in C#), which employs the UDDI SDK. The UDDI SDK requires that you set the Url static (shared) property of the Microsoft.Uddi.Inquire class first (assuming you are searching the registry rather than publishing to it). This means you can point the SDK to any standard UDDI implementation out there, not only the Microsoft one. In Figure 6, the code obtains the UDDI registry URL from the application's config file. Next, it instantiates a new GetBindingDetail object and then adds the supplied bindingKey to its BindingKeys collection. Calling getBindingDet.Send sends the request message to UDDI and returns a BindingDetail object, which contains a collection of BindingTemplates. Each binding template has an AccessPoint property that, in turn, has a Text property containing the service's URL. As long as the service owner keeps the UDDI listing up to date, this should be the current service location.

 

public string GetCurrentUrl(string bindingKey)

{

      try

      {

       //Set the URL of the UDDI registry we're using.

       //If the UDDI registry changes location,

       //you can change the URL in your application's

       //config file.

       Microsoft.Uddi.Inquire.Url = ConfigurationSettings

              .AppSettings["UddiInquireUrl"];

        //Instantiate a GetBindingDetail object.

       Microsoft.Uddi.GetBindingDetail getBindingDet=

             new Microsoft.Uddi.GetBindingDetail();

       //Add to it the binding key.

       getBindingDet.BindingKeys.Add(bindingKey);

       //Send the UDDI request

       //and get the binding detail back.

       Microsoft.Uddi.BindingDetail bd =

          getBindingDet.Send();

       //If there's information returned,

       if((bd!=null) &&

           (bd.BindingTemplates.Count > 0))

           //return the Text property of the

           //AccessPoint of the first binding template.

           //This assumes there's only one binding template,

           //which is usually the case.

           return bd.BindingTemplates[0]

                .AccessPoint.Text;

       else

    return "";

       }

      catch(System.Exception ex)

      {

         System.Diagnostics.Debug.WriteLine(

     "Error getting binding details\n " +

       ex.Message);

     return "";

    }

}

Figure 6. Here is the invocation pattern code. You can call UDDI to get the current service location.

 

Update the Client

Now you need to update the client to implement the invocation pattern (see Figure 6). I implemented the updated code (shown in Figure 7) in a file named TimeClientInvocationPattern.aspx. You'll need to copy InvocationPattern.dll and Microsoft.Uddi.Sdk.dll to your Web application's bin folder for this client to work.

 

When the user clicks on Get Time, the code attempts to invoke the Web Service as it did before. If an exception occurs, the Catch block instantiates an InvocationPattern object and calls its IsRecoverable method to determine whether this is an exception from which the code can recover.

 

If IsRecoverable returns True, the client calls GetCurrentUrl to get the new service's URL. The client reads the service's binding key from the application's config file. You'll need to update this config file with your own service's binding key, which you obtain from UDDI.

 

Then, the client sets the Web Service's proxy Url property to the URL returned from GetCurrentUrl and proceeds to call the Web Service at this new location.

 

To test the invocation pattern, rename ServerTime.asmx to NewServerTime.asmx. Then, sign in to UDDI and edit your Web Service registration. Change the Web Service URL to point to NewServerTime.asmx instead of ServerTime.asmx. Now, run TimeClientInvocationPattern.aspx and click on Get Time. First, the client will fail to call the service at its old location, but it will be able to recover using UDDI (see Figure 8).

 

Figure 7. This is updated client code to use the invocation pattern in the case of an exception. The code inside the Catch block uses the InvocationPattern class to determine whether the error is recoverable. If it is, a call to GetCurrentUrl queries UDDI for the current service URL.

 


Figure 8. The updated client can recover from 404 errors by getting the new service location from UDDI. This particular example is calling a service on learnxmlws.com instead of the original location, which was on localhost.

 

In this article, you learned how to leverage UDDI to implement the invocation pattern. With this pattern, clients can recover from failures due to Web Service relocation. The ability to locate Web Services at run time dynamically is one of the most useful features of UDDI.

 

The files referenced in this article are available for download.

 

Yasser Shohoud is a trainer and consultant specializing in XML Web Services. He is the author of Real World XML Web Services (Addison-Wesley). A Microsoft Most Valuable Professional (MVP) for ASP.NET, Yasser is active in the Web Services community and publishes the monthly.NET Web Services Newsletter at http://www.LearnXmlws.com/newsletter. Visit http://www.LearnXmlws.com for more information.

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish