C# Web Service調(diào)用Delphi時的注意事項
首先我覺得有必要把.net平臺下開發(fā)webservice進(jìn)行一個比較全面的闡述,web service的最初產(chǎn)生是在電子商務(wù)的環(huán)境下出現(xiàn)的,有些問題通過傳統(tǒng)的手段已經(jīng)不容易解決,比如在應(yīng)用程序之間進(jìn)行商務(wù)通信、數(shù)據(jù)交換,使用DCom、CORBA等二進(jìn)制機(jī)制的東西已經(jīng)行不通了,姑且不說他們受各自平臺的限制,比如DCom(Distribute Common Objects Model)只能在Windows平臺下進(jìn)行,而CORBA(Common Objects Request Broker Architecture)也有諸多限制。他們要實(shí)現(xiàn)應(yīng)用程序之間的數(shù)據(jù)通信是比較困難的。
在這種背景下,Web Services 應(yīng)運(yùn)而生,它很好的解決了跨語言、跨平臺以及良好而安全的穿透企業(yè)防火墻。它的體系結(jié)構(gòu)大體上分為五個層次:
HTTP(HyperText Transfer Protocol)信道下進(jìn)行數(shù)據(jù)通信
XML(Extensable Markup Language)數(shù)據(jù)表達(dá)形式
SOAP(Simple Objects Access Protocol)的數(shù)據(jù)封裝
WSDL(WebServices Description Language)的描述語言格式
UDDI(Universal Description and Discovery Integration) 統(tǒng)一的描述、發(fā)現(xiàn)和集成
作為它的優(yōu)點(diǎn)跨語言、跨平臺以及良好而安全的穿透企業(yè)防火墻已經(jīng)足以使我們感到興奮了。不過它也存在需要改善的地方,比如:
HTTP進(jìn)行數(shù)據(jù)通信存在速度較慢的情況,尤其是第一次聯(lián)結(jié)。需要一臺Web Server這一額外的開銷 說了WebServices的體系結(jié)構(gòu)以及其優(yōu)點(diǎn)缺點(diǎn)以后我們切入正題,那就是我們這次討論的話題:
C# Web Service調(diào)用Delphi時的問題
我們用一個檢驗WebMethod的Attribute的一個簡單的例子進(jìn)行闡述:它是完成一次從客戶A轉(zhuǎn)帳到B的一個簡單商務(wù)過程。
首先我們在.NET FrameWork1.1下創(chuàng)建一個WebService,這時候.net會幫我們自動創(chuàng)建一個Web應(yīng)用
我們需要創(chuàng)建一個類AttributeTest,它是在命名空間NameSpace AttributeTesting下的,那么這個類它將自動繼承了它的基類 System.Web.Services.WebService,需要支出的時,我們可以對這個Web應(yīng)用類設(shè)置其WebServiceAttribute,其中基本屬性包括Description 和NameSpace
- [WebServiceAttribute(Namespace=
 - "http://www.isdoo.com/services",
 - Description="HelloAnsel,ThisisatestingWebService!")]
 - publicclassAttributeTest:System.Web.Services.WebService
 - {
 - [WebMethodAttribute(Description="
 - 描述信息:繼承了Count方法,并且對名稱進(jìn)行重載。
 - 執(zhí)行的是把錢從A用戶轉(zhuǎn)帳到B用戶......",
 - //MessageName="ChangingMessageName",
 - BufferResponse=true,
 - CacheDuration=1000,
 - EnableSession=true,
 - TransactionOption=TransactionOption.RequiresNew)]
 - publicstringtransMoney(doubleMoney)
 - {
 - try
 - {
 - ContextUtil.EnableCommit();
 - //TransactiononlyusedtoDatabaseoperation!
 - MoneyInToA(Money);
 - MoneyOutFromB(Money);
 - ContextUtil.SetComplete();
 - return"TransactionSuccessful,total"+Money.ToString();
 - }
 - catch(Exceptione)
 - {
 - ContextUtil.SetAbort();
 - return"Transactionfailed!\n\r"+e.Message;
 - }
 - }
 - privatevoidMoneyInToA(doubleMoney)
 - {
 - SqlCommandsqlCom=newSqlCommand("updatebudgetsetMoney=
 - Money+"+Money.ToString()+"whereName='A'");
 - databaseAccessmyDatabase=newdatabaseAccess();
 - sqlCom.Connection=myDatabase.getConnection();
 - sqlCom.Connection.Open();
 - sqlCom.ExecuteNonQuery();
 - sqlCom.Connection.Close();
 - //thrownewException("OperationfailedwhentransfermoneyintoA!");
 - }
 - privatevoidMoneyOutFromB(doubleMoney)
 - {
 - SqlCommandsqlCom=newSqlCommand("updatebudgetsetMoney=
 - Money-"+Money.ToString()+"whereName='B'");
 - databaseAccessmyDatabase=newdatabaseAccess();
 - sqlCom.Connection=myDatabase.getConnection();
 - sqlCom.Connection.Open();
 - sqlCom.ExecuteNonQuery();
 - sqlCom.Connection.Close();
 - //thrownewException("OperationfailedwhentransfermoneyfromB!");
 - }
 - }
 
其中我們需要特別注意的是,WebMethodAttribute,這也是我們這一次需要講述的重點(diǎn)內(nèi)容,只要給一個方法加上[WebMethodAttribute],哪怕里面沒有任何屬性,那么WebService就會把這個方法暴露(Expose)給了客戶段調(diào)用者.下面我們講述一下它的6個屬性,其中包括2個描述性的信息屬性,4個功能屬性
- 描述性的信息屬性:
 - Description
 - MessageName
 - 4個功能性屬性:
 - BufferResponse
 - CacheDuration
 - EnableSession
 - TransactionOption
 
其中我們需要注意MessageName這個屬性它Delphi調(diào)用.NET平臺下開發(fā)的WebService的時候,如果你設(shè)置了MessageName這個Attribute的話,那么客戶端調(diào)用時會報錯誤。這也許是一個Bug,或許后面的版本會解決這個問題。至于這幾個屬性的具體功能就不再這里詳細(xì)描述了。大家可以去看看相關(guān)的書籍。
下面我把Delphi調(diào)用webservice的步驟列舉一下:
首先如果你只是開發(fā)調(diào)用客戶端,那么你只需要創(chuàng)建一個普通的應(yīng)用程序即可,然后需要你做的是,在工具欄WebServices下面找到SOAPHTTPClient這個控件,然后把它放在你的客戶端應(yīng)用窗體上;
其次就是你需要設(shè)置這個SOAPHTTPClient的屬性URL或者WSDL,這個內(nèi)容就是你的WebService的服務(wù)地址
比如我們當(dāng)前例子的服務(wù)地址是:http://localhost/AttributeTesting/AttributeTesting.asmx
如果你想輸入WSDL那么就是http://localhost/AttributeTesting/AttributeTesting.asmx?wsdl
這樣就完成了C# Web Service調(diào)用Delphi的控件設(shè)置;
然后我們需要引入服務(wù)器端的WSDL,你可以手工來做,也可以用Delphi提供的WebServices Importer功能來引入。
最后你只需要對引入的WSDL的接口進(jìn)行調(diào)用即可。在這里我們的對應(yīng)代碼是:
- procedure TForm1.BitBtn1Click(Sender: TObject);
 - var
 - aa:AttributeTestSoap;//這個就是WSDL下的類接口對象
 - msg:widestring;
 - bb:double;
 - begin
 - //HTTPRIO2 其實(shí)就是所謂的代理類,
 - 它負(fù)責(zé)進(jìn)行數(shù)據(jù)傳輸發(fā)送Request和接受Response的
 - aa:=HTTPRIO2 as AttributeTestSoap;
 - bb:=100.00;
 - msg:=aa.transMoney(bb);
 - //這就是調(diào)用web服務(wù)所暴露給我們的web服務(wù)方法WebMethod
 - showmessage(msg);
 - end;
 
這里我想再闡述一下C# Web Service調(diào)用Delphi的WebMethod的Attribute功能型屬性:
1 BufferResponse 
  BufferResponse如果為true,那么服務(wù)器端會在buffer滿了的時候才會把消息數(shù)據(jù)發(fā)送給調(diào)用者;如果為BufferResponse=false那么數(shù)據(jù)就會按照16K的字節(jié)塊的模式源源不斷地傳輸給客戶端調(diào)用者;
所以如果WebServices方法返回來的是比較大的一個數(shù)據(jù),比如返回來一個Dataset,那么用BufferResponse=true可以提高數(shù)據(jù)的傳輸效能。
2 CacheDuration
如果CacheDuration=1000,那么WebService就會把數(shù)據(jù)緩存在高速緩存中,如果在1000這個時間間隔內(nèi)訪問同樣的數(shù)據(jù),那么調(diào)用者會得到一個緩存數(shù)據(jù),而不是實(shí)時數(shù)據(jù)。這個屬性適用于每次查詢的數(shù)據(jù)沒有多大變化的情況。
3 EnableSession=true,    
是否保存狀態(tài)信息,本質(zhì)上WebService是一個SingleCall的模式,不應(yīng)該保存狀態(tài)信息的。在這種模式下,每個WebMethod的每次調(diào)用都會生成一個遠(yuǎn)程對象,所以說每個遠(yuǎn)程對象之間是沒有任何聯(lián)系的所以說這種模式下是不能保存狀態(tài)信息的。
但是你如果把EnableSession=true的話,那么你可以在WebService里面使用Session這個變量來保存一些狀態(tài)信息(默認(rèn)EnableSession=false)
4 TransactionOption
http://www.microsoft.com/China/Community/program/originalarticles/TechDoc/createWebServicebyVSNET.mspx
http://msdn.microsoft.com/library/cht/default.asp?url=/library/CHT/cpref/html/frlrfsystemwebserviceswebmethodattributeclassenablesessiontopic.asp
【編輯推薦】















 
 
 
 
 
 
 