轉(zhuǎn)帖|其它|編輯:郝浩|2010-09-16 14:08:17.000|閱讀 454 次
概述:本文將探討如何把.Net beta 2版整合進(jìn)其他平臺(tái),希望對(duì)大家有幫助。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
整合分布式應(yīng)用程序經(jīng)常是一件非常困難并且錯(cuò)綜復(fù)雜的任務(wù),即使是最富有經(jīng)驗(yàn)的開發(fā)者也可能會(huì)覺得頭疼。當(dāng)應(yīng)用程序在不同的操作系統(tǒng)以及涉及不同的程序平臺(tái)時(shí),這個(gè)集成問題變得尤其復(fù)雜。雖然說,Web服務(wù)承諾可以減輕程序員完成集成任務(wù)的困難程度,但是也可能給程序員們帶來一些意想不到的麻煩。在這里我們將把一個(gè)ASP.net應(yīng)用程序和一個(gè)PHP Web服務(wù)連結(jié)起來,以學(xué)習(xí)一些整合分布式應(yīng)用程序的方法,以及必要的應(yīng)對(duì)措施,包括運(yùn)行什么以及不用去做什么。
這個(gè)Web服務(wù)在一個(gè)Apache服務(wù)器上運(yùn)行,并且使用PHP開發(fā)。它從各種微軟新聞組檢索新聞?wù)约八鼈兊年P(guān)聯(lián)的文本。即使由這個(gè)服務(wù)提供的數(shù)據(jù)可以直接使用內(nèi)部的.Net對(duì)象存取,但是這個(gè)服務(wù)還是將使用并提供一個(gè)連接到非.Net平臺(tái)上的不錯(cuò)的演示。我們這里要討論的實(shí)例基于.Net beta 2版。
創(chuàng)建一個(gè)Web服務(wù)代理
Visual Studio.NET提供了一個(gè)出色的機(jī)制用于自動(dòng)地生成可用于存取遠(yuǎn)程Web服務(wù)的代理對(duì)像。因此,要首先嘗試使用這些函數(shù)來導(dǎo)入由PHP服務(wù)提供的Web服務(wù)描述語言(Web Services Description Language,WSDL)文件。 還可以使用.Net SDK的WSDL.exe命令行公用程序。不幸的是,在使用VS.net向?qū)?導(dǎo)入WSDL之后,并不能成功地創(chuàng)建一個(gè)代理。所以我必須把導(dǎo)入原始的WSDL文件后由VS.Net生成的文件轉(zhuǎn)換為WSDL:
1. 把模式域名空間從//www.w3.org/1999/XMLSchema改成//www.w3.org/2001/XMLSchema 然后清除所有的當(dāng)WSDL導(dǎo)入過程中由VS.Net添加的”q”域名空間。
2. 刪除 xmlns:tm=//microsoft.com/wsdl/mime/textMatching/和xmlns: mime="//schemas.xmlsoap.org/wsdl/mime/" 名字空間,因?yàn)檫@個(gè)應(yīng)用程序中不需要包含這些。
3. 刪除類型元素,因?yàn)樵嫉?WSDL文檔 并沒有包含Web服務(wù)的模式信息的指定的元素區(qū)段。
4. 改變輸入輸出元素消息屬性值為包含tns域名空間前綴的形式:
< portType name="nntpSoapPortType">
< operation name="getheaders" parameterOrder="newsgroup numitems">
< input message="tns:getheaders" />
< output message="tns:getheadersresponse" />
< /operation>
< operation name="getarticle" parameterOrder="newsgroup article">
< input message="tns:getarticle" />
< output message="tns:getarticleresponse" />
< /operation>
< /portType>
在進(jìn)行了下面的這些微小的改變,VS.Net向?qū)軌蜃x取WSDL并且自動(dòng)地生成一個(gè)代理。在編譯了這個(gè)代理之后,它被包含在一個(gè)ASP.NET頁面中。然而,當(dāng)這個(gè)ASP.Net頁面被執(zhí)行:“ message does not have a correct SOAP root XML tag.”,這個(gè)錯(cuò)誤被當(dāng)作一個(gè)SOAP錯(cuò)誤從Web服務(wù)中返回。為了精確地評(píng)估這個(gè)錯(cuò)誤,代理調(diào)用被一個(gè)名為Proxy Trace的公用程序使用,以便代理生成SOAP包裝。這可以通過把下列代碼添加進(jìn)ASP.Net頁面來實(shí)現(xiàn):
msNews.Proxy = new System.Net.WebProxy( //localhost:8080);
在察看了由.Net代理生成的SOAP包裝之后,我有點(diǎn)奇怪為什么會(huì)返回這個(gè)錯(cuò)誤,因?yàn)閷?shí)際上一個(gè)相對(duì)的SOAP包裝被生成并被發(fā)送到Web服務(wù)。即使在嘗試了好幾個(gè)轉(zhuǎn)化成代理代碼之后這個(gè)錯(cuò)誤依然持續(xù)。代碼段列表2顯示了從PHP Web服務(wù)返回的完整的SOAP錯(cuò)誤包裝。
在使用VS.Net中創(chuàng)建的代理對(duì)象的好幾個(gè)把ASP.Net頁面與PHP Web服務(wù)連結(jié)的不成功的嘗試之后,我決定從頭開始創(chuàng)建SOAP包裝以便執(zhí)行更有效的程序調(diào)試。{起先,它看起來好像由.Net代理生成的模式域名空間可能是問題的關(guān)鍵,因?yàn)?Net使用2001模式規(guī)范而PHP服務(wù)使用的是1999版本的規(guī)范。
然而,我把自定義的SOAP包裝改為用1999版本代替2001版本,錯(cuò)誤依然存在。在嘗試了好幾個(gè)其他的小的改變之后,我決定把SOAP包裝使用的域名空間前綴和正文元素從soap (由.Net代理生成)改為SOAP - ENV,因?yàn)槲铱匆娫赟OAP錯(cuò)誤信息中返回了SOAP - ENV前綴。(見代碼2)這表面上看上去微不足道的改變竟解決了問題!當(dāng)處理任何請(qǐng)求的時(shí)候,PHP服務(wù)顯然需要SOAP - ENV前綴,而拒絕不包含SOAP - ENV前綴的要求。
創(chuàng)建一個(gè)自定義代理
既然已經(jīng)了解了為什么Web服務(wù)返回一個(gè)SOAP錯(cuò)誤,我們就可以創(chuàng)建一個(gè)自定義代理來生成網(wǎng)服務(wù)期待的SOAP包裝。雖然創(chuàng)建一個(gè)自定義SOAP包裝肯定比使用一個(gè)由VS.net或者WSDL.exe公用程序生成的SOAP包裝要花更多的時(shí)間,但是這樣做可以完全控制包裝的內(nèi)容。為了開始創(chuàng)建自定義代理,我創(chuàng)建一個(gè)名為msnewsserviceproxy的包含兩個(gè)字段的新類:
public class MSNewsServiceProxy {
string _uri;
string _soapAction;
}
uri字段保存了Web服務(wù)的位置,而_soapAction字段保存了將要使用SOAP包裝發(fā)送的SOAPAction數(shù)據(jù)頭的名稱。在MSNewsServiceProxy類之內(nèi),添加CreateSoapEnvelope (),SendSoapEnvelope ()和FilterResult ()這三個(gè)方法。這些方法生成SOAP包裝請(qǐng)求,把它發(fā)送到Web服務(wù),然后過濾返回的SOAP包裝。讓我們逐一的看看每個(gè)方法。注意代碼在SOAP包裝的根元素上添加一個(gè)SOAP - ENV域名空間前綴。Web服務(wù)顯然需要這個(gè)特定的前綴,而拒絕任何不包含這個(gè)前綴的信息。因?yàn)閂S.net生成的代理發(fā)送一個(gè)soap域名空間前綴(而不是SOAP - ENV),所以它的消息被拒絕。Web服務(wù)不應(yīng)該需要一個(gè)特定的域名空間前綴而為此拒絕不帶此前綴的消息,但是域名空間問題也是你必須注意要想使工作更好的完成,要執(zhí)行一些看上去不{0>可思議的事情。
在SOAP包裝被創(chuàng)建之后,SendSoapEnvelope ()方法(見代碼段4)使用了幾個(gè)System.Net和System.IO域名空間中的類來把這個(gè)包裝發(fā)送到Web服務(wù)中。代碼首先通過把_uri變量傳送到對(duì)象構(gòu)造器來創(chuàng)建一個(gè)HttpWebRequest對(duì)象。其次,與這個(gè)請(qǐng)求相關(guān)聯(lián)的相應(yīng)的Method,ContentType和Header都將被發(fā)送。然后一個(gè)StreamWriter對(duì)象和HttpWebRequest對(duì)象的請(qǐng)求流相關(guān)聯(lián),SOAP包裝就被使用StreamWriter的Write ()方法寫到流中。
從Web服務(wù)返回的SOAP包裝被HttpWebResponse對(duì)象的SendSoapEnvelope ()方法獲得。
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
如果應(yīng)答不是空值,它將被載入一個(gè)XMLTextReader,XMLTextReader被用來填充XmlDocument對(duì)象。然后從這個(gè)方法中返回XmlDocument對(duì)象。
FilterSoapEnvelope ()方法分析SOAP應(yīng)答包裝并把從Web服務(wù)中返回的數(shù)據(jù)裝入自定義代理的“消費(fèi)者”使用的XmlDocument對(duì)象:
private XmlDocument
FilterSoapEnvelope(
XmlDocument doc) {
XmlDocument filterDoc =new XmlDocument();
XmlNode result = doc.SelectSingleNode("//results");
XmlNode resultImport = filterDoc.ImportNode(result,true);
filterDoc.AppendChild(resultImport);
return filterDoc;
}
雖然過濾器可以使用好幾種方法執(zhí)行,但是FilterSoapEnvelope ()方法依靠XPath語句可以在應(yīng)答SOAP包裝中得到結(jié)果元素。
微軟新聞組PHP Web服務(wù)展示了允許取得新聞組新聞?wù)?的兩種方法:getheaders ()和getmessage ()。 你可以看到如何在自定義代理類中使用這兩種方法(見代碼段5)。 注意每個(gè)方法中的代碼傳遞Web服務(wù)方法名被調(diào)用到CreateSoapEnvelope ()方法和任何使用這個(gè)方法關(guān)聯(lián)的參數(shù)。 在SOAP包裝被發(fā)送以及應(yīng)答被接受之后,F(xiàn)ilterSoapEnvelope ()方法被調(diào)用來把返回的數(shù)據(jù)加載到一個(gè)XmlDocument對(duì)象中,同樣,這個(gè)對(duì)象也是代理“消費(fèi)者”使用的。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:網(wǎng)絡(luò)轉(zhuǎn)載