現在,我們可以轉換一下角色,看看應用程序的客戶端部分。在設計時,我們也許可以在 UDDI 中找到此 Web 服務。我們將下載相應的 WSDL 文件并使用 Microsoft Visual Studio? .NET 的 Add Web Reference(添加 Web 引用)或 WSDL.exe 生成一個代理類。(WSDL.exe 是一個命令行工具,屬于 Microsoft .NET 框架 SDK 的一部分。)
現在可以開始編寫客戶端應用程序中的邏輯。在本例中,它是稱為 SalesReportClient.exe 的 C# Windows 窗體應用程序,答應用戶查詢銷售報表信息。 首先,需要將 UDDI .NET SDK 類添加到項目中,可以下載這些類。(Microsoft UDDI SDK 版本 1.5.2 [英文] 與 Visual Studio .NET Beta 2 兼容;Microsoft UDDI .NET SDK Beta 版本 1.75 [英文] 與 Visual Studio .NET Release Candidate 兼容。) using 聲明如下:using System;
using Microsoft.Uddi.Binding; 然后,需要將 UDDI 服務器的入口點存儲在此 Web 服務所在的位置(究竟,UDDI 本身就是一個 Web 服務)。要執行此操作,需要為此 .exe 可執行文件創建一個應用程序配置文件,用于存儲 UDDI 服務器的位置。Web 服務的 bindingKey 也將存儲在此配置文件中。通過在 .NET 中使用 XML 配置文件,您可以添加任意數量的 appSetting,應用程序可以通過集合獲取。<?xml version="1.0" encoding="utf-8" ?>
</configuration> 在此示例中,我們指向駐留在自己的計算機上的 Microsoft UDDI Developer Edition 服務器。UDDI_URL 也可以是公共 UDDI 節點之一,或者是駐留在企業內部的 UDDI 注冊表。使用配置文件 app.config 的命名規則來保存此文件。編譯應用程序后,配置文件將被放在 /bin 目錄中,并使用它自己的 .exe 名稱命名。 剛剛完成的這個步驟(添加有關 Web 服務的配置信息),與 Visual Studio .NET 如何在添加到項目的每個 Web 引用上公布 URL Behavior 屬性并沒有什么不同。通過將該屬性更改為 dynamic,Visual Studio .NET 可以創建包含 Web 服務入口點的配置文件。上述操作通過提供在運行時重新查詢 UDDI 的功能,進一步擴展了此概念。因此,配置文件包含了 UDDI 節點的入口點和 Web 服務的 bindingKey。進入討論組討論。
現在,我們可以開始對應用程序本身進行編碼。首先需要創建一個文本框、一個標簽、一個按鈕和兩個日期時間選擇器。然后建立一些全局變量: //應用程序的一些變量
PRivate string InquiryURL = null;
private string bindingKey = null;
private string accessPoint = null;
private BindingTemplate BT;
private double salesFigure = 0; 窗體被實例化以后,我們需要初始化以下變量:
public Form1()
{
//
//Windows 窗體設計器支持所必需
//
InitializeComponent(); //從配置文件導入變量
InquiryURL = ConfigurationSettings.AppSettings["UDDI_URL"];
bindingKey = ConfigurationSettings.AppSettings["bindingKey"];
bool InitCache = RefreshCacheFromUDDI();
if ( InitCache == true ) accessPoint = bt.AccessPoint.Text; } RefreshCacheFromUDDI() 函數用于查詢 UDDI 服務器以查找入口點。使用 UDDI SDK 執行 UDDI API 調用 (GetBindingDetail),將 bindingKey 作為參數傳遞。 private bool RefreshCacheFromUDDI()
{
//使用 UDDI SDK,設置 UDDI 入口點
Inquire.Url = InquiryURL;
//創建 get_bindingDetail UDDI API 消息
GetBindingDetail gbd = new GetBindingDetail();
//添加 bindingKey
gbd.BindingKeys.Add( bindingKey );
try
{
BindingDetail bd = gbd.Send();
//假如成功,則使用返回集合中的第一個
模板 //更新 bindingTemplate 對象
bt = bd.BindingTemplates[0];
return true;
}
catch (Exception err)
{
textBox1.Text += err.Message;
return false;
}
}
在應用程序運行期間,我們將入口點的位置放在變量中。假如用戶要重新啟動應用程序,它將在 UDDI 中重新查詢入口點,因此應用程序始終擁有對 Web 服務的最新更改。假如需要,可以將這些數據緩存在文件系統或數據庫中。 接下來,需要創建調用 Web 服務自身的函數: private bool InvokeWebService()
{
localhost.SalesReport sr = new localhost.SalesReport();
//為代理類設置入口點
sr.Url = accessPoint;
try
{
salesFigure = sr.GetSalesTotalByRange( dateTimePicker1.Value,
dateTimePicker2.Value );
label1.Text = "選定日期的銷售圖表:$" +
salesFigure.ToString();
textBox1.Text += "Web 服務調用成功!";
return true;
}
catch (Exception err)
{
textBox1.Text += err.Message;
return false;
}
} 最后,用戶單擊按鈕時,應用程序將嘗試調用 Web 服務。 private void button1_Click(object sender, System.EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
//嘗試調用 Web 服務
bool WebServiceSUCcess = InvokeWebService();
//假如失敗,則查詢 UDDI
if ( WebServiceSuccess == false )
{
textBox1.Text += "Web 服務失敗。重新查詢 UDDI
以獲取新的入口點。/n/n";
bool UDDISuccess = RefreshCacheFromUDDI();
//重新查詢 UDDI 成功,
if ( UDDISuccess == true )
{
//將原入口點與新入口點進行比較
//確定是否有所變化
if ( accessPoint.Equals( bt.AccessPoint.Text ) == false)
{
//假如入口點不同,則一定是新的
//重設變量
accessPoint = bt.AccessPoint.Text; //并嘗試再次調用 Web 服務
WebServiceSuccess = InvokeWebService();
//無法使用新信息調用 Web 服務
new info
if ( WebServiceSuccess == false )
{
textBox1.Text += "Web 服務再次失敗。UDDI 中已更新的入口點無效!/n/n";
} }
else
{
textBox1.Text += "UDDI 未提供新信息。/n/n";
}
}
else
{
textBox1.Text += "UDDI 刷新失敗。/n/n";
}
}
} 請注重如何在運行時為 Web 服務代理類設置入口點。因為所有代理類都是從 System.Web.Services.Protocols.SoapHttpClientProtocol 中衍生出來的,所以代理類會公布一系列屬性,.Url 屬性就是其中之一。設置此屬性使我們能夠在運行時指定入口點。然后,我們可以通過線路發送 SOAP 請求。假如沒有發生異常,則表示一切正常并且從 Web 服務返回的數據顯示在窗體中。但假如確實發生異常,此函數返回“假”,調用代碼將嘗試從 UDDI 刷新入口點,以重新使用 RefreshCacheFromUDDI() 函數。 重新查詢 UDDI 之后,我們會將 UDDI 返回的入口點與原入口點進行比較。假如入口點相同,則提供者尚未使用新信息更新 UDDI,我們所能做的只有嘗試與 Web 服務的提供者聯系,告訴他們 Web 服務不響應。但是,假如從 UDDI 檢索到的入口點不同,則可以嘗試再次調用 Web 服務。 為模擬故障,可以更改 Web 服務的名稱。嘗試運行應用程序。然后,用 Web 服務的新名稱更新 UDDI 項。再次運行應用程序。應用程序將在 UDDI 中找到新的入口點,成功查詢新服務,然后保存此信息。假如您完全關閉應用程序,再重新打開,則第一次嘗試時應該能夠再次調用 Web 服務。 其他方案
這個“失敗時重試”示例討論的是 UDDI 可在運行時用作 Web 服務客戶端的支持基礎結構。在以后的專欄中,我們將討論其他方案,包括: 優化入口點查找 - 可能有多個 Web 服務支持駐留在不同服務器上的公共接口,這些服務器又位于不同的物理位置。客戶端應使用最近的 Web 服務。通過運行時 UDDI 查找,客戶可以根據不同服務的地理分類或與該實現關聯的其他元數據來確定最佳入口點。
基于公共接口聚合數據 - WSDL 中可能定義了一種用于搜索目錄的標準 Web 服務接口。該行業的很多供給商都可以實現 Web 服務接口,并在 UDDI 中發布入口點。在運行時,客戶端應用程序可以動態搜索這些入口點并發出查詢以收集這種編錄數據。通過這種方式,輪詢應用程序可以利用運行時 UDDI 數據。
此外,我們還將討論如何優化 WSDL 文件,使其真正充當接口說明文件。
總結
UDDI 提供了重要的運行時功能,可以集成到應用程序中以創建更強壯的動態客戶端。通過將 UDDI 用作 Web 服務體系結構中的基礎結構,可以編寫更加可靠的應用程序。進入討論組討論。