C# Web Service調用Delphi時的注意事項
首先我覺得有必要把.net平臺下開發webservice進行一個比較全面的闡述,web service的最初產生是在電子商務的環境下出現的,有些問題通過傳統的手段已經不容易解決,比如在應用程序之間進行商務通信、數據交換,使用DCom、CORBA等二進制機制的東西已經行不通了,姑且不說他們受各自平臺的限制,比如DCom(Distribute Common Objects Model)只能在Windows平臺下進行,而CORBA(Common Objects Request Broker Architecture)也有諸多限制。他們要實現應用程序之間的數據通信是比較困難的。
在這種背景下,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的體系結構以及其優點缺點以后我們切入正題,那就是我們這次討論的話題:
C# 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="HelloAnsel,ThisisatestingWebService!")]
- publicclassAttributeTest:System.Web.Services.WebService
- {
- [WebMethodAttribute(Description="
- 描述信息:繼承了Count方法,并且對名稱進行重載。
- 執行的是把錢從A用戶轉帳到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,這也是我們這一次需要講述的重點內容,只要給一個方法加上[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
這樣就完成了C# Web Service調用Delphi的控件設置;
然后我們需要引入服務器端的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;
這里我想再闡述一下C# Web Service調用Delphi的WebMethod的Attribute功能型屬性:
1 BufferResponse
BufferResponse如果為true,那么服務器端會在buffer滿了的時候才會把消息數據發送給調用者;如果為BufferResponse=false那么數據就會按照16K的字節塊的模式源源不斷地傳輸給客戶端調用者;
所以如果WebServices方法返回來的是比較大的一個數據,比如返回來一個Dataset,那么用BufferResponse=true可以提高數據的傳輸效能。
2 CacheDuration
如果CacheDuration=1000,那么WebService就會把數據緩存在高速緩存中,如果在1000這個時間間隔內訪問同樣的數據,那么調用者會得到一個緩存數據,而不是實時數據。這個屬性適用于每次查詢的數據沒有多大變化的情況。
3 EnableSession=true,
是否保存狀態信息,本質上WebService是一個SingleCall的模式,不應該保存狀態信息的。在這種模式下,每個WebMethod的每次調用都會生成一個遠程對象,所以說每個遠程對象之間是沒有任何聯系的所以說這種模式下是不能保存狀態信息的。
但是你如果把EnableSession=true的話,那么你可以在WebService里面使用Session這個變量來保存一些狀態信息(默認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
【編輯推薦】