首先我覺得有必要把.net平台下開發webservice進行一個比較全面的闡述,web service的最初產生是在電子商務的環境下出現的,有些問題通過傳統的手段已經不容易解決,比如在應用程式之間進行商務通訊、資料交換,使用DCom、CORBA等二進位機制的東西已經行不通了,姑且不說他們受各自平台的限制,比如DCom(Distribute Common Objects Model)只能在Windows平台下進行,而CORBA(Common Objects Request Broker Architecture)又只是Java平台下的產物。他們要實現應用程式之間的資料通訊是比較困難的。
在這種背景下,Web Services 應運而生,它很好的解決了跨語言、跨平台以及良好而安全的穿透企業防火牆。它的體繫結構大體上分為五個層次:
HTTP(HyperText Transfer Protocol)通道下進行資料通訊
XML(Extensable Markup Language)資料表達形式
SOAP(Simple Objects Access Protocol)的資料封裝
WSDL(WebServices Description Language)的描述語言格式
UDDI(Universal Description and Discovery Integration) 統一的描述、發現和整合
作為它的優點跨語言、跨平台以及良好而安全的穿透企業防火牆已經足以使我們感到興奮了。不過它也存在需要改善的地方,比如:
HTTP進行資料通訊存在速度較慢的情況,尤其是第一次連接。
需要一台Web Server這一額外的開銷
說了WebServices的體繫結構以及其優點缺點以後我們切入正題,那就是我們這次討論的話題:
Web Service 服務在Delphi下調用時的問題
閑話少說,我們用一個檢驗WebMethod的Attribute的一個簡單的例子進行闡述:它是完成一次從客戶A轉帳到B的一個簡單商務過程。
首先我們在.NET FrameWork1.1下建立一個WebService,這時候.net會幫我們自動建立一個Web應用
我們需要建立一個類AttributeTest,它是在命名空間NameSpace AttributeTesting下的,那麼這個類它將自動繼承了它的基類 System.Web.Services.WebService,需要支出的時,我們可以對這個Web應用類設定其WebServiceAttribute,其中基本屬性包括Description 和NameSpace
[WebServiceAttribute(Namespace="http://www.isdoo.com/services",
Description="Hello Ansel,This is a testing Web Service!")]
public class AttributeTest : System.Web.Services.WebService
{
[WebMethodAttribute(Description="描述資訊:繼承了Count方法,並且對名稱進行重載。執行的是把錢從A使用者轉帳到B使用者......",
//MessageName="Changing MessageName",
BufferResponse=true,
CacheDuration=1000,
EnableSession=true,
TransactionOption=TransactionOption.RequiresNew)]
public string transMoney(double Money)
{
try
{
ContextUtil.EnableCommit();//Transaction only used to Database operation!
MoneyInToA(Money);
MoneyOutFromB(Money);
ContextUtil.SetComplete();
return "Transaction Successful,total "+Money.ToString();
}
catch( Exception e)
{
ContextUtil.SetAbort();
return "Transaction failed! \n\r "+e.Message;
}
}
private void MoneyInToA(double Money)
{
SqlCommand sqlCom = new SqlCommand("update budget set Money=Money+"+Money.ToString()+" where Name='A'");
databaseAccess myDatabase = new databaseAccess();
sqlCom.Connection=myDatabase.getConnection();
sqlCom.Connection.Open();
sqlCom.ExecuteNonQuery();
sqlCom.Connection.Close();
//throw new Exception("Operation failed when transfer money into A!");
}
private void MoneyOutFromB(double Money)
{
SqlCommand sqlCom = new SqlCommand("update budget set Money=Money-"+Money.ToString()+" where Name='B'");
databaseAccess myDatabase = new databaseAccess();
sqlCom.Connection=myDatabase.getConnection();
sqlCom.Connection.Open();
sqlCom.ExecuteNonQuery();
sqlCom.Connection.Close();
//throw new Exception("Operation failed when transfer money from B!");
}
}
其中我們需要特別注意的是,WebMethodAttribute,這也是我們這一次需要講述的重點內容,只要給一個方法加上[WebMethodAttribute],哪怕裡面沒有任何屬性,那麼WebService就會把這個方法暴露(Expose)給了客戶段調用者.下面我們講述一下它的6個屬性,其中包括2個描述性的資訊屬性,4個功能屬性
描述性的資訊屬性:
Description
MessageName
4個功能性屬性:
BufferResponse
CacheDuration
EnableSession
TransactionOption
其中我們需要注意MessageName這個屬性它Delphi調用.NET平台下開發的WebService的時候,如果你設定了MessageName這個Attribute的話,那麼用戶端調用時會報錯誤。這也許是一個Bug,或許後面的版本會解決這個問題。至於這幾個屬性的具體功能就不再這裡詳細描述了。大家可以去看看相關的書籍。
下面我把Delphi調用webservice的步驟列舉一下:
首先如果你只是開發調用用戶端,那麼你只需要建立一個普通的應用程式即可,然後需要你做的是,在工具列WebServices下面找到SOAPHTTPClient這個控制項,然後把它放在你的用戶端應用表單上;
其次就是你需要設定這個SOAPHTTPClient的屬性URL或者WSDL,這個內容就是你的WebService的服務地址
比如我們當前例子的服務地址是:http://localhost/AttributeTesting/AttributeTesting.asmx
如果你想輸入WSDL那麼就是http://localhost/AttributeTesting/AttributeTesting.asmx?wsdl
這樣就完成了控制項設定;
然後我們需要引入伺服器端的WSDL,你可以手工來做,也可以用Delphi提供的WebServices Importer功能來引入。
最後你只需要對引入的WSDL的介面進行調用即可。在這裡我們的對應代碼是:
procedure TForm1.BitBtn1Click(Sender: TObject);
var
aa:AttributeTestSoap;//這個就是WSDL下的類介面對象
msg:widestring;
bb:double;
begin
//HTTPRIO2 其實就是所謂的代理類,它負責進行資料轉送發送Request和接受Response的
aa:=HTTPRIO2 as AttributeTestSoap;
bb:=100.00;
msg:=aa.transMoney(bb);//這就是調用web服務所暴露給我們的web服務方法WebMethod
showmessage(msg);
end;