建立Web Service
我將用c#建立一個Web Service 叫SecurityWebService。一個Web Service檔案的副檔名是:.asmx(就象asp.net的副檔名.aspx那樣),檔案的第一行是:
<%@ WebService Language="C#" class="SecurityWebService" %>
這個語句的含義是:告訴編譯器運行Web Service模式,還有c#類名。我們還需要訪問Web Service名字空間,這也是引用系統名字空間的一次好實踐。
using System;
using System.Web.Services;
SecurityWebService 應該繼承了Web Service類的功能,因此我們有必要加入下面這行代碼
public class SecurityWebService : WebService
現在我們使用物件導向的編程技巧建立一個類,c#的類與c++和java非常相似,用C#建一個類件象去公園散步那樣簡單,而且不需要任何技巧。
C#的基礎資料型別 (Elementary Data Type)設計的非常聰明,因此,如果我們返回"int," "float," 或者 "string" ,那麼將自動將他們轉變成標準Xml輸出。不幸的是,在大多數例子中我們需要將獲得的資料集合看成一個單一的實體(single entity)。現在我們舉一個例子。
我們的 SecurityWebService 股票報價系統需要使用者輸入股票代號,並且還將返回完整的公司名和現行股票價格,所以對一隻股票而言我們有三個資訊塊。
1、公司代碼(string)
2、公司名(string)
3、價格(double)
當我們提交股票時,我們需要提取所有三種資料,有幾種方法來完成這項工作,最好的方法是將他們綁定到一種可被枚舉的資料類型內,我們在c#中可用"struct"來完成,c#中的"struct"和c++中的結構很相似。
public struct SecurityInfo
{
public string Code;
public string CompanyName;
public double Price;
}
我們可以通過模組建立Web Service,代碼如下:
<%@ WebService Language="C#" class="SecurityWebService" %>
using System;
using System.Web.Services;
public struct SecurityInfo
{
public string Code;
public string CompanyName;
public double Price;
}
public class SecurityWebService : WebService
{
private SecurityInfo Security;
public SecurityWebService()
{
Security.Code = "";
Security.CompanyName = "";
Security.Price = 0;
}
private void AssignValues(string Code)
{
// This is where you use your business components.
// Method calls on Business components are used to populate the data.
// For demonstration purposes, I will add a string to the Code and
// use a random number generator to create the price feed.
Security.Code = Code;
Security.CompanyName = Code + " Pty Ltd";
Random RandomNumber = new System.Random();
Security.Price = double.Parse(new System.Random(RandomNumber.Next(1,10)).NextDouble().Format("##.##",null));
}
[WebMethod(Description="This method call will get the company name and the price for a given security code.",EnableSession=false)]
public SecurityInfo GetSecurityInfo(string Code)
{
AssignValues(Code);
SecurityInfo SecurityDetails = new SecurityInfo();
SecurityDetails.Code = Security.Code;
SecurityDetails.CompanyName = Security.CompanyName;
SecurityDetails.Price = Security.Price;
return SecurityDetails;
}
}
記住所有使用者都能通過http訪問Web Service,也許你會談到代碼中的機密商業資料和不希望其他人知道的資料,怎樣保守資料機密。解決方案是保護商業邏輯功能塊,只允許訪問展示層,在c#中可以通過使用關鍵字"[Web Method]"來達到這個目的,我們看看下面的代碼:
[WebMethod(Description="This......",EnableSession=false)]
public SecurityInfo GetSecurityInfo(string Code)
這個函數顯示給公眾,description標記用於描述Web Service的功能,由於我們不能儲存任何會話資料,我們就將消除工作階段狀態。
private void AssignValues(string Code)
這個商業邏輯函數不被公眾所知,我們不希望敏感的商業資訊被公布在web上(注意:甚至將private改為public,公眾仍然看不見,為什麼呢?,這是由於沒有使用[Web Method]關鍵字。)
我們可以在這個函數中利用商業邏輯獲得最新的股票報價,為了這個目的,我在代碼中添加了文字框以便輸入公司名稱,價格由一個隨機函數產生。
我們把這個檔案以SampleService.asmx儲存在IIS目錄下。我將他儲存在虛擬目錄"/work/aspx"下,在WEB瀏覽器中的相似如:
這個WEB頁是由.NET framework產生的,我們沒有建立這個頁(這是由系統自動產生的,我們沒有為他寫任何一行代碼,這附圖是先前代碼的副產品),準備使用的功能對單一的Web Service是相當合適的。
使用asp.net和config.web檔案可以很輕鬆的改變該頁。不過要注意那個SDL規範的連結(即使我們我們使用WSDL,.NET 版仍然引用了SDL,這個問題在下一個版本中有希望矯正),這是Web Service的一個描述檔案目的是建立一個代理對象,這基本上給出Web Service的一個大致介紹,如果你對這些都比較熟悉,你可以只看"Web-only"方法,SDL規範對所有私人函數和屬性都未描述,SecurityWebService 類的SDL規範在常式A中看到。
怎樣使用Web Service
現在我們能夠使用這個Web Service了,讓我們輸入一個值獲得一個假的價格。
點擊Invoke按鈕,將顯示一個下面這樣的新視窗和Xml文檔。
這顯示了Web Service怎樣發布資訊,我們需要設計一個用戶端來顯示Xml文檔,這個用戶端應該是:
1、一個Web 頁
2、控制台或Windows應用程式
3、能和行動電話互動的WML或Wmlscript
4、能在PDA上使用的Palm或Windows ce應用程式
在後面我將解釋建立用戶端的過程
可以通過http get方法直接調用Web Service,在這個例子中將不通過上面的web頁和點擊invoke按鈕獲得Xml文檔,我們直接用http get方法調用Xml文檔,那麼文法應下:
http://server/webServiceName.asmx/functionName?parameter=parameterValue
所以對我們這個例子而言,語句將是:
http://localhost/work/aspx/SampleService.asmx/GetSecurityInfo?Code=IBM
這與點擊invoke按鈕效果一樣,將產生同樣的結果。
現在我們知道怎樣建立並使用一個Web Service,但我們的工作還只完成了一半。怎樣使用戶端發現Web Service呢?在internet網上通過什麼途徑搜尋Web Service呢?是否通過象雅虎搜尋引擎那樣的搜尋引擎呢?為瞭解決這些問題我們需要為Web Service建立一個"discovery" 檔案。
建立"discovery" 檔案
發現Web Service是詢問並定位Web Service描述的過程,是訪問Web Service的預備過程,用戶端通過發現Web Service的過程獲得Web Service的存在,大小,怎樣和他互動,"discovery" 檔案是一個副檔名為 :.disco的Xml文檔。不必強制性地要求為每個Web Service建立一個"discovery" 檔案,下面是本文例子的"discovery" 檔案執行個體:
<?Xml version="1.0" ?>
<dynamicDiscovery Xmlns="urn:schemas-
dynamicdiscovery:disco.2000-03-17">
</dynamicDiscovery>
配置Web Service
配置Web Service非常簡單,與asp.net應用檔案相似,將.asmx和.disco檔案複製到相應的目錄下就行了。
Web Service的將來
Web Service的將來是非常光明的,現在不單是微軟在發展Web Service技術,IBM和SUN也致力於發展Web Service,SOAP toolkits已經可以在Apache 和 Java Web servers上使用,不過我相信對於Web Service還需要做一點工作,尤其是Web Service發現過程,她實在是太原始了。
Web Service將在WEB上映入一些新的觀念,有一點我相信是付費瀏覽,就象付費電視一樣,我們建立WEB網站並對使用者收費, 就象付費電視一樣,使用者只需要付一點費用,這在商業上是可行的。
附執行個體A
<?Xml version="1.0" ?>
<serviceDescription Xmlns:s0="http://tempuri.org/" name="SecurityWebService" targetNamespace="http://tempuri.org/"
Xmlns="urn:schemas-Xmlsoap-org:sdl.2000-01-25">
<soap Xmlns="urn:schemas-Xmlsoap-org:soap-sdl-2000-01-25">
<service>
<addresses>
<address uri="http://localhost/work/aspx/SampleService.asmx" />
</addresses>
<requestResponse name="GetSecurityInfo" soapAction="http://tempuri.org/GetSecurityInfo">
<request ref="s0:GetSecurityInfo" />
<response ref="s0:GetSecurityInfoResult" />
<info>This method call will get the company name and the price for a given security code.</info>
</requestResponse>
</service>
</soap>
<httppost Xmlns="urn:schemas-Xmlsoap-org:post-sdl-2000-01-25">
<service>
<requestResponse name="GetSecurityInfo" href="http://localhost/work/aspx/SampleService.asmx/GetSecurityInfo">
<request>
<form>
<input name="Code" />
</form>
</request>
<response>
<mimeXml ref="s0:SecurityInfo" />
</response>
<info>This method call will get the company name and the price for a given security code.</info>
</requestResponse>
</service>
</httppost>
<httpget Xmlns="urn:schemas-Xmlsoap-org:get-sdl-2000-01-25">
<service>
<requestResponse name="GetSecurityInfo" href="http://localhost/work/aspx/SampleService.asmx/GetSecurityInfo">
<request>
<param name="Code" />
</request>
<response>
<mimeXml ref="s0:SecurityInfo" />
</response>
<info>This method call will get the company name and the price for a given security code.</info>
</requestResponse>
</service>
</httpget>
<schema targetNamespace="http://tempuri.org/" attributeFormDefault="qualified"
elementFormDefault="qualified" Xmlns="http://www.w3.org/1999/XmlSchema">
<element name="GetSecurityInfo">
<complexType>
<all>
<element name="Code" Xmlns:q1="http://www.w3.org/1999/XmlSchema" type="q1:string" nullable="true" />
</all>
</complexType>
</element>
<element name="GetSecurityInfoResult">
<complexType>
<all>
<element name="result" type="s0:SecurityInfo" />
</all>
</complexType>
</element>
<complexType name="SecurityInfo">
<all>
<element name="Code" Xmlns:q2="http://www.w3.org/1999/XmlSchema" type="q2:string" nullable="true" />
<element name="CompanyName" Xmlns:q3="http://www.w3.org/1999/XmlSchema" type="q3:string" nullable="true" />
<element name="Price" Xmlns:q4="http://www.w3.org/1999/XmlSchema" type="q4:double" />
</all>
</complexType>
<element name="SecurityInfo" type="s0:SecurityInfo" />
</schema>
</serviceDescription>