C# Web Service調(diào)用Delphi時(shí)的注意事項(xiàng)
首先我覺得有必要把.net平臺(tái)下開發(fā)webservice進(jìn)行一個(gè)比較全面的闡述,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)行不通了,姑且不說他們受各自平臺(tái)的限制,比如DCom(Distribute Common Objects Model)只能在Windows平臺(tái)下進(jìn)行,而CORBA(Common Objects Request Broker Architecture)也有諸多限制。他們要實(shí)現(xiàn)應(yīng)用程序之間的數(shù)據(jù)通信是比較困難的。
在這種背景下,Web Services 應(yīng)運(yùn)而生,它很好的解決了跨語言、跨平臺(tái)以及良好而安全的穿透企業(yè)防火墻。它的體系結(jié)構(gòu)大體上分為五個(gè)層次:
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)跨語言、跨平臺(tái)以及良好而安全的穿透企業(yè)防火墻已經(jīng)足以使我們感到興奮了。不過它也存在需要改善的地方,比如:
HTTP進(jìn)行數(shù)據(jù)通信存在速度較慢的情況,尤其是第一次聯(lián)結(jié)。需要一臺(tái)Web Server這一額外的開銷 說了WebServices的體系結(jié)構(gòu)以及其優(yōu)點(diǎn)缺點(diǎn)以后我們切入正題,那就是我們這次討論的話題:
C# Web Service調(diào)用Delphi時(shí)的問題
我們用一個(gè)檢驗(yàn)WebMethod的Attribute的一個(gè)簡單的例子進(jìn)行闡述:它是完成一次從客戶A轉(zhuǎn)帳到B的一個(gè)簡單商務(wù)過程。
首先我們在.NET FrameWork1.1下創(chuàng)建一個(gè)WebService,這時(shí)候.net會(huì)幫我們自動(dòng)創(chuàng)建一個(gè)Web應(yīng)用
我們需要?jiǎng)?chuàng)建一個(gè)類AttributeTest,它是在命名空間NameSpace AttributeTesting下的,那么這個(gè)類它將自動(dòng)繼承了它的基類 System.Web.Services.WebService,需要支出的時(shí),我們可以對這個(gè)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)容,只要給一個(gè)方法加上[WebMethodAttribute],哪怕里面沒有任何屬性,那么WebService就會(huì)把這個(gè)方法暴露(Expose)給了客戶段調(diào)用者.下面我們講述一下它的6個(gè)屬性,其中包括2個(gè)描述性的信息屬性,4個(gè)功能屬性
- 描述性的信息屬性:
- Description
- MessageName
- 4個(gè)功能性屬性:
- BufferResponse
- CacheDuration
- EnableSession
- TransactionOption
其中我們需要注意MessageName這個(gè)屬性它Delphi調(diào)用.NET平臺(tái)下開發(fā)的WebService的時(shí)候,如果你設(shè)置了MessageName這個(gè)Attribute的話,那么客戶端調(diào)用時(shí)會(huì)報(bào)錯(cuò)誤。這也許是一個(gè)Bug,或許后面的版本會(huì)解決這個(gè)問題。至于這幾個(gè)屬性的具體功能就不再這里詳細(xì)描述了。大家可以去看看相關(guān)的書籍。
下面我把Delphi調(diào)用webservice的步驟列舉一下:
首先如果你只是開發(fā)調(diào)用客戶端,那么你只需要?jiǎng)?chuàng)建一個(gè)普通的應(yīng)用程序即可,然后需要你做的是,在工具欄WebServices下面找到SOAPHTTPClient這個(gè)控件,然后把它放在你的客戶端應(yīng)用窗體上;
其次就是你需要設(shè)置這個(gè)SOAPHTTPClient的屬性URL或者WSDL,這個(gè)內(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;//這個(gè)就是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ù)器端會(huì)在buffer滿了的時(shí)候才會(huì)把消息數(shù)據(jù)發(fā)送給調(diào)用者;如果為BufferResponse=false那么數(shù)據(jù)就會(huì)按照16K的字節(jié)塊的模式源源不斷地傳輸給客戶端調(diào)用者;
所以如果WebServices方法返回來的是比較大的一個(gè)數(shù)據(jù),比如返回來一個(gè)Dataset,那么用BufferResponse=true可以提高數(shù)據(jù)的傳輸效能。
2 CacheDuration
如果CacheDuration=1000,那么WebService就會(huì)把數(shù)據(jù)緩存在高速緩存中,如果在1000這個(gè)時(shí)間間隔內(nèi)訪問同樣的數(shù)據(jù),那么調(diào)用者會(huì)得到一個(gè)緩存數(shù)據(jù),而不是實(shí)時(shí)數(shù)據(jù)。這個(gè)屬性適用于每次查詢的數(shù)據(jù)沒有多大變化的情況。
3 EnableSession=true,
是否保存狀態(tài)信息,本質(zhì)上WebService是一個(gè)SingleCall的模式,不應(yīng)該保存狀態(tài)信息的。在這種模式下,每個(gè)WebMethod的每次調(diào)用都會(huì)生成一個(gè)遠(yuǎn)程對象,所以說每個(gè)遠(yuǎn)程對象之間是沒有任何聯(lián)系的所以說這種模式下是不能保存狀態(tài)信息的。
但是你如果把EnableSession=true的話,那么你可以在WebService里面使用Session這個(gè)變量來保存一些狀態(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
【編輯推薦】