WebMethod框架:實現(xiàn)Web服務(wù)的更高效方法
在 Microsoft .NET 中,目前有兩種截然不同的方法來實現(xiàn)基于 HTTP 的 Web 服務(wù)。第一種同時也是最低級的方法是編寫一個自定義 IHttpHandler 類并將它插入到 .NET HTTP 管道中。這種方法要求您使用 System.Web API 來處理傳入的 HTTP 消息,使用 System.Xml API 來處理在 HTTP 主體中找到的 SOAP 封裝。編寫自定義處理程序還要求您手動編寫一個精確描述您的實現(xiàn)的 WSDL 文檔。要正確地做好這一切,需要對 XML、XSD、SOAP 和 WSDL 規(guī)范有深入的了解,但這個先決條件使大多數(shù)人望而卻步。
實現(xiàn) Web 服務(wù)的一種更高效的方法是使用 Microsoft ASP.NET WebMethod框架。ASP.NET 為 .asmx 終結(jié)點附帶了一個特殊的 IHttpHandler 類(名為 WebServiceHandler),該類提供您所需的可反復(fù)套用的 XML、XSD、SOAP 和 WSDL 功能。由于 WebMethod 框架使您從復(fù)雜的基礎(chǔ) XML 技術(shù)中解脫出來,因此您可以將精力迅速集中到手頭的業(yè)務(wù)問題上。
圖 1. 靈活性和工作效率之間的折衷
在實現(xiàn)技術(shù)之間進(jìn)行選擇就會形成如圖 1 中所示的靈活性和工作效率之間常見的折衷。編寫自定義的 IHttpHandler 會為您提供極大的靈活性,但卻要花大量的時間來編寫、測試和調(diào)試代碼。WebMethod 框架使迅速生成和運行 Web 服務(wù)變得非常輕松,但是您無疑將受到該框架邊界的限制。但是,如果 WebMethod框架不能完全滿足您的需要,也可以通過添加自己的額外功能來擴展該框架。
WebMethod框架
WebMethod框架圍繞將 SOAP 消息映射到 .NET 類上的方法來設(shè)計。這通過首先用在 System.Web.Services \命名空間中找到的 [WebMethod] 屬性批注您的方法來完成。例如,下面的 .NET 類包含四種方法,其中的兩種方法用 [WebMethod] 屬性進(jìn)行批注:
- using System.Web.Services;
- public class MathService
- {
- [WebMethod]
- public double Add(double x, double y) {
- return x + y;
- }
- [WebMethod]
- public double Subtract(double x, double y) {
- return x - y;
- }
- public double Multiply(double x, double y) {
- return x * y;
- }
- public double Divide(double x, double y) {
- return x / y;
- }
- }
要在 WebMethod框架中使用該類,需要將該類編譯成程序集,然后將它復(fù)制到虛擬目錄的 bin 目錄中。在本例中,Add 和 Subtract 方法隨后可被公開為 Web 服務(wù)操作,而 Multiply 和 Divide 卻不能(因為它們沒有被標(biāo)記為 [WebMethod])。
通過 .asmx 終結(jié)點將 Add 和 Subtract 公開為 Web 服務(wù)操作。為此,要新建一個名為 Math.asmx 且包含以下簡單聲明的文本文件,然后將它放到包含該程序集的同一虛擬目錄中(注:這是放在虛擬目錄本身中,而不是它的 bin 子目錄):
- < %@ WebService class="MathService"%>
上面的聲明通知 .asmx 處理程序要在哪個類中查找 WebMethod,該處理程序就會神奇地處理其余所有事情。例如,假設(shè)虛擬目錄的名稱為 'math',它包含 Math.asmx 以及一個包含該程序集的 bin 子目錄,瀏覽到 http://localhost/math/math.asmx 會導(dǎo)致 .asmx 處理程序生成如圖 2 所示的文檔頁(后面會對此進(jìn)行詳述)。
關(guān)于 .asmx 處理程序如何工作有一個很大的變化。.asmx 文件通常只包含 WebService 聲明,該聲明根據(jù)名稱引用 Web 服務(wù)類(這與上面顯示的聲明相似)。因此,在本例中,程序集必須已經(jīng)被編譯和部署到虛擬目錄的 bin 目錄中。對于在 .asmx 文件中找到的源代碼,.asmx 處理程序還提供實時編譯。例如,下面的文件(名為 Mathjit.asmx)包含 WebService 聲明以及被引用類的源代碼。
- < @% WebService class="MathServiceJit" language="C#"%>
- using System.Web.Services;
- public class MathServiceJit
- {
- [WebMethod]
- public double Add(double x, double y) {
- return x + y;
- }
- [WebMethod]
- public double Subtract(double x, double y) {
- return x - y;
- }
- public double Multiply(double x, double y) {
- return x * y;
- }
- public double Divide(double x, double y) {
- return x / y;
- }
- }
當(dāng)通過 HTTP 首次訪問此文件時,.asmx 處理程序會編譯源代碼并將程序集部署到正確的位置。請注意,WebService 聲明還必須提供語言,以便 .asmx 處理程序在運行時能夠選擇正確的編譯器。這種方法的明顯缺點是,只有在首次訪問該文件之后,才會發(fā)現(xiàn)編譯錯誤。
圖 2. MathService 文檔
當(dāng)您在 Visual Studio? .NET 中新建一個 Web 服務(wù)項目時,總是使用“雙文件”技術(shù),即類的源文件與引用它的 .asmx 文件是分開的。集成開發(fā)環(huán)境 (IDE) 盡量地對文件進(jìn)行了隱藏,但是如果您在 Solution Explorer 工具欄上單擊 Show All Files,將會注意到該項目中的每個 Web 服務(wù)類都有兩個文件。實際上,Visual Studio .NET 并不支持 .asmx 文件的語法突出顯示或 IntelliSense?,所以,如果您朝著這個方向設(shè)計,則必須依靠自己。對于 Web 項目,Visual Studio .NET 也負(fù)責(zé)自動創(chuàng)建一個虛擬目錄并將程序集編譯到該虛擬目錄的 bin 目錄中。
在詳細(xì)討論 .asmx 處理程序如何工作之前,讓我們先簡單討論一下消息如何從 Internet Information Server (IIS) 傳遞到 .asmx 處理程序。當(dāng)傳入的 HTTP 消息到達(dá)端口 80 時,IIS 使用在 IIS 元數(shù)據(jù)庫中找到的信息來確定應(yīng)當(dāng)使用哪個 ISAPI DLL 來處理消息。.NET 安裝程序?qū)?.asmx 擴展名映射到 Aspnet_isapi.dll,如圖 3 所示。
圖 3. .asmx 的 IIS 應(yīng)用程序映射
Aspnet_isapi.dll 是 .NET 框架提供的標(biāo)準(zhǔn)的 ISAPI 擴展名,它只是將 HTTP 請求轉(zhuǎn)發(fā)到一個名為 Aspnet_wp.exe 的單獨的輔助進(jìn)程。Aspnet_wp.exe 宿主公共語言運行庫和 .NET HTTP 管道。當(dāng)消息進(jìn)入 .NET HTTP 管道之后,該管道會在配置文件中進(jìn)行查找,看對于給定的擴展名應(yīng)當(dāng)使用哪個 IHttpHandler 類。如果您在 Machine.config 文件中進(jìn)行查找,則會發(fā)現(xiàn)它包含 .asmx 文件的 httpHandler 映射,如下所示:
- < configuration>
- < system.web>
- < httpHandlers>
- < add verb="*" path="*.asmx" type="System.Web.Services.Protocols.WebServiceHandlerFactory,
- System.Web.Services, Version=1.0.3300.0, Culture=neutral,
- PublicKeyToken=b03f5f7f11d50a3a" validate="false"/>
- ...
因此,當(dāng)消息進(jìn)入面向 .asmx 文件的 .NET HTTP 管道時,該管道會調(diào)用 WebServiceHandlerFactory 類,以便實例化新的 WebServiceHandler 對象,該對象可用于處理請求(通過調(diào)用 IHttpHandlerProcessRequest 方法)。WebServiceHandler 對象隨后打開物理 .asmx 文件,以便確定包含 WebMethod 的類的名稱。有關(guān) .NET HTTP 管道如何工作的詳細(xì)信息,請查看 HTTP Pipelines:Securely Implement Request Processing, Filtering, and Content Redirection with HTTP Pipelines in ASP.NET。
當(dāng) .asmx 處理程序由 .NET HTTP 管道調(diào)用之后,它會開始神奇地處理 XML、XSD、SOAP 和 WSDL。
【編輯推薦】