關於c#下寫的web service 服務在delphi下呼叫時的問題
首先我覺得有必要把.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;
ok! that's all!
商業源碼熱門下載www.html.org.cn