分散式應用程式整合向來充滿挑戰,尤其是當涉及不同作業系統與技術平台時。雖然 Web Service 承諾降低整合難度,但實務上仍常遇到互通性問題。本文以實際案例示範:如何讓 ASP.NET 應用程式成功呼叫運行於 Apache 上的 PHP Web Service,並解決過程中遇到的 SOAP 協議不相容、命名空間衝突等棘手問題。
目標 PHP Web Service 部署於 Apache 伺服器,提供從 Microsoft 新聞群組擷取文章標題與內容的功能。雖然資料本可直接用 .NET 物件存取,但此案例旨在展示跨平台整合的完整流程與應對策略。開發環境基於 .NET Framework Beta 2。
Visual Studio .NET 提供 WSDL 匯入精靈與 WSDL.exe 命令列工具,可自動產生 Web Service Proxy 類別。然而,直接匯入 PHP 服務的 WSDL 卻無法成功產生可用的 Proxy。經分析,原始 WSDL 使用 1999 版 XML Schema 命名空間,且包含 .NET 不需要的 MIME 相關命名空間與型別定義。
對原始 WSDL 進行以下調整後,VS.NET 精靈才能正常產生 Proxy:
https://www.w3.org/1999/XMLSchema 改為 https://www.w3.org/2001/XMLSchema,並移除 VS.NET 匯入時自動加入的 q 命名空間前綴。xmlns:tm="https://microsoft.com/wsdl/mime/textMatching/" 與 xmlns:mime="https://schemas.xmlsoap.org/wsdl/mime/" 命名空間。<types> 元素,因原始 WSDL 未包含具體結構描述。<portType> 中 <input>、<output> 的 message 屬性,加上 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>
編譯產生的 Proxy 並引用於 ASP.NET 頁面後,執行卻拋出 SOAP 錯誤:"message does not have a correct SOAP root XML tag"。使用 Proxy Trace 工具攔截封包發現,.NET Proxy 產生的 SOAP Envelope 使用 soap: 前綴,而 PHP 服務回傳的錯誤封包卻使用 SOAP-ENV: 前綴。經測試,將自訂 SOAP 封包的根元素前綴從 soap 改為 SOAP-ENV 後,呼叫即告成功。顯見該 PHP 服務強制要求特定前綴,違反 SOAP 規範的寬鬆原則,但在跨平台整合中必須妥協因應。
由於自動產生的 Proxy 無法滿足特殊需求,決定手工構建 SOAP 封包,實作自訂 Proxy 類別 MSNewsServiceProxy,核心包含三個方法:
CreateSoapEnvelope():依方法名與參數動態組裝 SOAP 封包,關鍵在於根元素使用 SOAP-ENV: 前綴。SendSoapEnvelope():利用 HttpWebRequest/HttpWebResponse 發送封包並接收回應,回傳 XmlDocument。FilterSoapEnvelope():以 XPath //results 從回應中提取業務資料,回傳精簡的 XmlDocument 供上層使用。完整程式碼包含 getHeaders()、getMessage() 兩個公開方法,分別對應 PHP 服務的 getheaders、getarticle 操作。
在 Page_Load 中實例化自訂 Proxy,呼叫 getHeaders() 取得新聞標題清單,繫結至 Label 控制項顯示;點擊標題時以 JavaScript 開啟新視窗載入 msNewsMessage.aspx 顯示文章全文。錯誤處理採用統一捕獲例外並顯示友善訊息。
文章附有完整的 SOAP 請求/回應封包範例(代碼段 1、2)、自訂 Proxy 實作(代碼段 3~5)、ASP.NET 頁面程式碼(代碼段 6、7)以及前端 .aspx 檔案,可供參考實作細節。
雖然多數 Web Service 可透過 VS.NET 或 WSDL.exe 自動產生 Proxy,但跨平台整合時仍可能因命名空間、編碼、前綴等細節差異導致互通失敗。掌握手工構建 SOAP 封包與自訂 Proxy 的能力,是解決此類棘手整合問題的關鍵利器。