asp.net|web|web服務 摘要:本文講解微軟ASP.NET Web服務方法(WebMethod)是如何提供高效率的建立Web服務的途徑的。WebMethod可以把傳統的微軟.NET方法暴露為Web服務作業,支援HTTP、XML、XML Schema、SOAP和WSDL。WebMethod(.asmx)處理處理常式能自動地把輸入的SOAP訊息傳遞給適當的方法,並自動地把輸入的XML元素序列化為相應的.NET對象。
介紹
目前在微軟.NET中實現基於HTTP的Web服務有兩種根本不同的途徑。最底層的技術是編寫一個插入.NET HTTP管道的自訂IHttpHandler類。這種途徑要求你使用System.Web API來處理輸入的HTTP訊息,使用System.Xml API處理HTTP體中的SOAP封裝。編寫自訂處理常式要求你手工建立正確描述實現的WSDL文檔。嚴格執行所有的這些操作要求你非常瞭解XML、XSD、SOAP和WSDL規範,但是這對於大多數開發人員來說很困難。
實現Web服務的效率更高的途徑是使用微軟ASP.NET WebMethods架構組件。ASP.NET為.asmx終結點(稱為WebServiceHandler)發布了一個特定的IHttpHandler類,它提供必要的XML、XSD、SOAP和WSDL功能的範本檔案。因為WebMethods架構組件把你從下層XML技術的複雜性中解放了出來,你能夠快速聚焦於手頭的業務問題。
圖1:靈活性和生產率之間的折衷
在實現技術之間作出選擇形成了圖1中所示的靈活性和生產率之間的折衷。編寫自訂的IhttpHandler給了你無限大的靈活性,但是要花費你很長時間編寫、測試和調試代碼。WebMethods架構組件使建立自己的Web服務和快速運行變得很容易,但是很明顯你要受到該架構組件界限的限制。但是,在WebMethods架構組件不能提供你完全需要的資訊的情況下,可以通過添加自己的附加功能來擴充該架構組件。
通常,除非你已經掌握了XML、XSD、SOAP和WSDL並且原意承擔直接處理它們的負擔,最好不要專註於Web服務所需要的WebMethods架構組件。它提供了大多數Web服務端點(endpoints)所需要的基本服務,以及能把架構組件進行"彎曲"來適合你的精確的需要的一些有趣的可擴充能力。本文是基於這種假定討論WebMethods如何工作的內部資訊。如果你不太瞭解XML Schema和SOAP,可以參閱Understanding XML Schema和Understanding SOAP。
WebMethods架構組件
WebMethods架構組件迴圈地把SOAP訊息映射到.NET類中的方法。這種功能的實現首先需要把你的方法註解為System.Web.Services名字空間中的[WebMethod]屬性。例如,下面的.NET類包含四個方法,其中兩個使用[WebMethod]屬性註解了:
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; }}
為了在WebMethods架構組件重使用這個類,你需要把這個類編譯為一個組件(assembly)並把它複製到虛擬目錄的bin目錄中。在這個例子中,Add和Subtract方法可以被暴露作為Web服務作業,但是Multiply和Divide卻不能(因為它們沒有使用[WebMethod]標記)。
你可以通過一個.asmx端點(endpoint)把Add和Subtract暴露為Web服務作業。為了實現這個功能,建立一個名為Math.asmx的包含下面的簡單聲明的新文字檔,並把它放到包含該組件的虛擬目錄中(注意:它自己進入虛擬目錄而不是子目錄bin中):
<%@ WebService class="MathService"%>
這個聲明告訴.asmx處理常式使用哪個類檢查WebMethods,並且該處理常式自動處理其它的資訊。例如,假定虛擬目錄叫作"math"並且它包含了Math.asmx,並且bin子目錄包含了該組件,那麼瀏覽http://localhost/math/math.asmx將導致.asmx處理常式產生圖2所示的文檔頁面。
這與.asmx處理常式如何工作有較大的變化。.asmx檔案通常只包含通過名字引用Web服務類(如上所示)的WebService聲明。因此,在這種情況下,該組件必須已經被編譯好、配置到了虛擬目錄的bin目錄中。.asmx處理常式也提供.asmx檔案中原始碼的just-in-time(即時)編譯。例如,下面的檔案(叫作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; }}
第一次通過HTTP訪問這個檔案時,.asmx處理常式編譯原始碼並把組件配置到正確的位置。注意WebService聲明必須提供語言,這樣.asmx處理常式才能在運行時選擇正確的編譯器。這種方法的一個明顯的問題是直到你第一次訪問該檔案時才會發現編譯錯誤。
圖2:MathService文檔
當你使用Visual Studio .NET建立一個新的Web服務項目時,它通常使用"雙檔案"技術,把源檔案與引用它的.asmx檔案分開。整合式開發環境(IDE)隱藏了這些檔案,但是你可以點擊"解決方案瀏覽器"工具條上的Show All Files(顯示所有檔案),你會發現項目中的每個Web服務類都有兩個檔案。實際上,Visual Studio .NET並不支援.asmx檔案的高亮度提醒或IntelliSense。有了Web項目後,Visual Studio .NET也處理建立虛擬目錄並自動把組件編譯到虛擬目錄的bin目錄中。
在深入分析.asmx處理常式如何工作前,我們先簡短討論一下來自IIS的訊息如何指派到用於處理的.asmx處理常式中。當輸入的HTTP訊息到達80連接埠時,IIS使用自己的中繼資料庫(metabase)的資訊來找出使用哪一個ISAPI DLL來處理這個訊息。.NET安裝程式把.asmx擴充映射到Aspnet_isapi.dll,如圖3所示。
圖3:.asmx 的IIS應用程式對應
Aspnet_isapi.dll是.NET架構組件提供的一個標準的ISAPI擴充,它簡單地把HTTP請求轉寄到單獨的叫作Aspnet_wp.exe的背景工作處理序中。Aspnet_wp.exe寄宿了通用語言運行時和.NET HTTP管道。一旦訊息進入.NET HTTP管道,管道就查詢設定檔,看應該使用哪一個IhttpHandler類處理給定的擴充。如果你查看Machine.config檔案,你會發現它包含了.asm檔案的一個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"/>...
因此當某個目標為.asmx檔案的訊息進入.NET HTTP管道時,該管道調用WebServiceHandlerFactory類來執行個體化用於處理這個請求的新的WebServiceHandler對象。WebServiceHandler對象開啟物理的.asmx檔案以決定包含WebMethods的類的名稱。
一旦.asmx處理常式被.NET HTTP管道調用,它就開始處理XML、XSD、SOAP和WSDL進程。.asmx處理常式提供的功能可以分為三個部分:1)訊息發送;2)把XML映射到對象;3)自動化WSDL和文檔產生。下面講詳細講解每一部分。
訊息發送
當HTTP管道調用.asmx處理常式時,它通過查看.asmx檔案中的WebService聲明來找出使用哪個.NET類來檢查。接著它查看輸入的HTTP訊息的資訊以正確地決定調用被引用類地哪個方法。為了調用前面的例子中顯示的Add操作,輸入的HTTP訊息必須有類似下面的資訊:
POST /math/math.asmx HTTP/1.1Host: localhostContent-Type: text/xml; charset=utf-8Content-Length: lengthSOAPAction: "http://tempuri.org/Add"<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <Add xmlns="http://tempuri.org/"> <x>33</x> <y>66</y> </Add> </soap:Body></soap:Envelope>
在輸入的HTTP訊息中的確有兩部分資訊可以用於找出調用類中的哪個方法:SOAPAction頭部或者請求的元素名稱(例如soap:Body元素內的元素名稱)。在這種情況下,任何一個都表明了寄件者希望調用的方法的名稱。
預設情況下.asmx處理常式使用SOAPAction頭部的值來執行訊息發送。因此,.asmx 處理常式查看訊息中的SOAPAction頭部,接著使用.NET反射(reflection)檢查被引用類中的方法。它只考慮使用[WebMethod]標誌標記的方法,但是它通過查看每個方法的SOAPAction值來正確地決定調用哪個方法。因為我們沒有在自己的類的方法中明確指定SOAPAction的值,.asmx處理常式就假定SOAPAction的值是Web服務的名字空間後面跟上方法名稱的組合。因為我們也沒有指定名字空間,處理常式就把http://tempuri.org作為預設值。因此Add方法的預設的SOAPAction值是http://tempuri.org/Add。
你可以使用[WebService]標誌作為類的註解來自訂Web服務的名字空間,使用下面所說明的[SoapDocumentMethod]標誌作為WebMethods的註解來指定SOAPAction的值:
using System.Web.Services;using System.Web.Services.Protocols;[WebService(Namespace="http://example.org/math")]public class MathService{ [WebMethod] public double Add(double x, double y) { return x + y; } [WebMethod] [SoapDocumentMethod(Action="urn:math:subtract")] public double Subtract(double x, double y) { return x - y; } ...}
現在.asmx處理常式認為Add 方法的SOAPAction的值為http://example.org/math/Add(使用預設的啟發學習法),Subtract方法的為urn:math:subtract(因為我們明確地定義了這個值)。例如,下面的HTTP請求訊息調用Subtract操作:
POST /math/math.asmx HTTP/1.1Host: localhostContent-Type: text/xml; charset=utf-8Content-Length: lengthSOAPAction: "urn:math:subtract"<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <Subtract xmlns="http://example.org/math"> <x>33</x> <y>66</y> </Subtract> </soap:Body></soap:Envelope>
如果.asmx處理常式無法尋找到匹配輸入的HTTP訊息的SOAPAction,它簡單地拋出一個異常(後面將解釋異常如何處理)。如果你不願意依賴SOAPAction頭部來進行方法調度,你可以指示.asmx處理常式通過使用[SoapDocumentService]標誌的RoutingStyle屬性作為類的註解來使用請求元素地名稱。如果你這樣做了,你大概也會通過把SOAPAction的值設定為空白字串來表明WebMethods不需要SOAPAction值:
using System.Web.Services;using System.Web.Services.Protocols;[WebService(Namespace="http://example.org/math")][SoapDocumentService( RoutingStyle=SoapServiceRoutingStyle.RequestElement)]public class MathService{ [WebMethod] [SoapDocumentMethod(Action="")] public double Add(double x, double y) { return x + y; } [WebMethod] [SoapDocumentMethod(Action="")] public double Subtract(double x, double y) { return x - y; } ...}
在這種情況下,處理常式不會查看SOAPAction值--它使用請求元素的名稱作為代替。例如,它認為Add方法的請求元素的名稱為Add(來自http://example.org/math名字空間),下面示範了這種HTTP請求訊息:
POST /math/math.asmx HTTP/1.1Host: localhostContent-Type: text/xml; charset=utf-8Content-Length: lengthSOAPAction: ""<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <Add xmlns="http://example.org/math"> <x>33</x> <y>66</y> </Add> </soap:Body></soap:Envelope>
因此,.asmx處理常式接收到一個輸入的HTTP請求時,第一件重要的事情是找出怎樣把這個訊息發送到對應的WebMethod。但是在能夠實際調用該方法前,它需要把輸入的XML映射到.NET對象。
把XML映射到對象
一旦WebMehod處理常式找出了將調用哪個方法,接著它就需要把XML訊息轉換為可以提供給方法調用的.NET對象。在訊息發送後,處理常式通過反射檢查該類找出如何處理輸入的XML訊息以達到這個目的。System.Xml.Serialization名字空間中的XmlSerializer類執行XML和對象之間的自動對應。
XmlSerializer使任何公用的.NET類型映射到XML Schema類型成為可能,並且有了類似的映射,它可以在.NET對象和XML執行個體文檔之間自動對應(圖4所示)。目前XmlSerializer被限制為XML Schema所支援的模型,因此不能處理目前現代的物件模型(例如複雜的非樹型對象圖表、兩重指標等等)的所有複雜性。然而,XmlSerializer可以處理開發人員趨向使用的大多數複雜的類型。
對於上面的例子中所示的Add方法,XmlSerializer會把x和y元素映射到.NET雙精確度型值,那麼調用Add時它們就可以使用了。Add方法給調用者返回一個雙精確度型值,接著需要序列化該值返回為SOAP響應中的一個XML元素。
圖4:把XML映射到對象
XmlSerializer也能自動處理複雜的類型(除了上面描述的限制)。例如,下面的WebMethod計算兩個Point(點)結構體之間的距離。
using System;using System.Web.Services;public class Point { public double x; public double y;}[WebService(Namespace="urn:geometry")]public class Geometry { [WebMethod] public double Distance(Point orig, Point dest) { return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) + Math.Pow(orig.y-dest.y, 2)); }}
這種操作的SOAP請求訊息將包含一個Distance元素,該元素包含兩個子項目,一個叫作orig,另一個叫dest,它們每個都包含兩個子項目x和y,如下所示:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <Distance xmlns="urn:geometry"> <orig> <x>0</x> <y>0</y> </orig> <dest> <x>3</x> <y>4</y> </dest> </Distance> </soap:Body></soap:Envelope>
這種情況下的SOAP響應訊息將包含一個DistanceResponse元素,該元素包含一個雙精確度類型的DistanceResult元素:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <DistanceResponse xmlns="urn:geometry"> <DistanceResult>5</DistanceResult> </DistanceResponse> </soap:Body></soap:Envelope>
預設的XML映射使用方法的名稱作為請求元素的名稱,參數的名稱作為它的子項目的名稱。每個參數的結構依賴於類型的結構。公用欄位和屬性的名稱簡單地映射到子項目(這種情況下是Point中的x和y)。預設情況下響應元素的名稱是請求元素的名稱後面加上"Response"。響應元素也包含一個子項目,名稱為請求元素的名稱加上"Result"。
你可以使用一系列內建的映射標誌從標準的XML映射中解放出來。例如,你可用使用[XmlType]標誌自訂類型的名稱和名字空間。你可以使用[XmlElement]和[XmlAttribute]標誌來控制參數或類成員如何分別映射到元素或屬性。你可以使用[SoapDocumentMethod]標誌來控制方法自身如何映射到請求/響應訊息中的元素名稱。例如,你可以看一看下面版本的Distance樣本的多種標誌:
using System;using System.Web.Services;using System.Web.Services.Protocols;using System.Xml.Serialization;public class Point { [XmlAttribute] public double x; [XmlAttribute] public double y;}[WebService(Namespace="urn:geometry")]public class Geometry { [WebMethod] [SoapDocumentMethod(RequestElementName="CalcDistance", ResponseElementName="CalculatedDistance")] [return: XmlElement("result")] public double Distance( [XmlElement("o")]Point orig, [XmlElement("d")]Point dest) { return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) + Math.Pow(orig.y-dest.y, 2)); }}
這個版本的Distance要求輸入的SOAP訊息格式如下:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <CalcDistance xmlns="urn:geometry"> <o x="0" y="0" /> <d x="3" y="4" /> </CalcDistance> </soap:Body></soap:Envelope>
它產生的SOAP響應訊息的格式如下:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <CalculatedDistance xmlns="urn:geometry"> <result>5</result> </CalculatedDistance> </soap:Body></soap:Envelope>
該.asmx處理常式使用SOAP document/literal樣式來實現和描述上面所示的預設映射。這意味著該WSDL定義將包含描述SOAP訊息中所使用的請求和響應元素的字面上的XML schema定義(例如,沒有使用SOAP編碼規則)。
該.asmx處理常式也可以使用SOAP rpc/encoded樣式。這意味著SOAP主體(Body)包含一個RPC調用的XML表現,並且參數都使用SOAP編碼規則序列化了(例如,不需要XML Schema)。為了達到這個目標,使用[SoapRpcService]和[SoapRpcMethod]代替[SoapDocumentService]和[SoapDocumentMethod]標誌。如果你要瞭解這些樣式之間的差別,請參閱Understanding SOAP。
從上面的資訊中你可以發現,完全地自訂如何把給定的方法映射到SOAP訊息是可能的。XmlSerializer提供了強大的序列化引擎以及許多我們在此文中沒有討論的特性。如果你要瞭解XmlSerializer如何工作的詳細資料,請查閱Moving to .NET and Web Services。
作為處理參數的並行化的補充,.asmx處理常式也能夠並行化/序列化SOAP頭部。SOAP頭部的處理方法與參數不同,因為典型情況下它們被認為是範圍之外的資訊,沒有直接關聯到某個特定的方法。由於這個原因,典型的頭部處理是由監聽層完成的,使WebMethod根本不用進行頭部處理。
但是,如果你希望在WebMethod中處理頭部資訊,你必須提供一個示範自SoapHeader(它描述了頭部的XML Schema類型)的.NET類。接著你定義該類型的一個成員變數作為頭部執行個體的位置標誌符。最後,你給每個需要訪問該頭部的WebMethod作註解,指定你需要處理的欄位的名稱。
例如,看一看下面的包含用於身分識別驗證目的的UsernameToken頭部的SOAP請求:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header> <x:UsernameToken xmlns:x="http://example.org/security"> <username>Mary</username> <password>yraM</password> </x:UsernameToken> </soap:Header> <soap:Body> <CalcDistance xmlns="urn:geometry"> ...
為了使.asmx處理常式能夠並行化該頭部,首先你必須定義一個描述隱含的XML Schema類型的.NET類(注意:如果你已經有了該頭部的XML Schema,那麼可以使用xsd.exe /c產生這個類)。在這種情況下,相應的類如下所示:
[XmlType(Namespace="http://example.org/security")][XmlRoot(Namespace="http://example.org/security")]public class UsernameToken : SoapHeader { public string username; public string password;}
接著,你必須在WebMethod類中簡單地定義一個成員變數來保持該頭部類的一個執行個體,並使用[SoapHeader]標誌來註解該WebMethod,如下所示:
using System;using System.Web.Services;using System.Web.Services.Protocols; [WebService(Namespace="urn:geometry")]public class Geometry { public UsernameToken Token; [WebMethod] [SoapHeader("Token")] public double Distance(Point orig, Point dest) { if (!Token.username.Equals(Reverse(Token.password))) throw new Exception("access denied"); return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) +Math.Pow(orig.y-dest.y, 2)); }}
接著,在WebMethod中你可以訪問該頭部提供的Token欄位並提取資訊。你也可以使用相同的技術把該頭部送回給用戶端--你只需要在[SoapHeader]標誌聲明中簡單地指定頭部的方向。需要瞭解在WebMethod架構組件中處理SOAP頭部的更多資訊,請查閱Digging into SOAP Headers with the .NET Framework。
.asmx處理常式也提供了.NET異常的自動的序列化。任何被.asmx捕捉到的沒有處理的異常都自動地序列化進入響應中的SOAP Fault元素。例如,在前面的例子中,如果使用者名稱與與密碼不匹配,代碼將拋出一個.NET異常。接著.asmx處理常式捕捉到這個異常並序列化到下面所示的SOAP響應中:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <soap:Fault> <faultcode>soap:Server</faultcode> <faultstring>Server was unable to process request. --> access denied</faultstring> <detail /> </soap:Fault> </soap:Body></soap:Envelope>
如果你需要更多地SOAP Fault元素控制權,可以明確地拋出一個SoapException對象,指定所有的SOAP Fault元素細節,例如faultcode、faulstring、faultactor和detail元素。你可以參閱Using SOAP Faults獲得更多資訊。
如上所示,指出WebMethod如何工作必須瞭解下層序列化引擎和它的多種選項。序列化引擎的優點是它隱藏了所有的通常在編寫自訂處理常式中需要的下層XML API代碼。但是,儘管大多數開發人員發現這是有正面意義的,有一些開發人員認為它是一個缺陷,因為它們仍然希望在WebMethod實現中手動封裝SOAP訊息。要瞭解如何?這種混合的途徑的詳細資料,請參閱Accessing Raw SOAP Messages in ASP.NET Web Services。
自動產生WSDL
一旦你已經編寫並配置了一個WebMethod,用戶端為了成功地與它通訊,需要瞭解正確地SOAP訊息是什麼樣子的。提供Web服務描述的標準的途徑是WSDL(或嵌入式XSD定義)。為了協助適應這種情況,.asmx處理常式自動產生人類可以閱讀的文檔頁面和準確反映WebMethod介面的WSDL定義。如果你給WebMethods應用了一系列的映射標誌,它們都會反映在產生的文檔中。
如果你瀏覽.asmx檔案,你會看到類似圖2所示的可以閱讀的文檔頁面。該文檔頁面是由一個叫作DefaultWsdlHelpGenerator.aspx的.aspx頁面(位置在C:\windows\Microsoft.NET\Framework\ v1.0.3705\config)產生的。如果開啟這個檔案,你可以發現這僅僅是一個使用.NET反射產生文檔的標準的ASP.NET頁面。這個特性使你的文檔一直與代碼同步。你可以簡單地修改這個檔案來自訂產生的文檔。
你可以通過在Web.config檔案中指定一個不同的文檔檔案來繞過在虛擬目錄基礎上的文檔產生:
<configuration> <system.web> <webServices> <wsdlHelpGenerator href="MyDocumentation.aspx"/> </webServices> ...
如果用戶端提出的.asmx端點的GET請求在請求字串中有"?wsdl",那麼.asmx處理常式會產生WSDL定義來代替可以閱讀的文檔。用戶端可以使用這個WSDL定義來產生自動瞭解如何與Web服務通訊的代理類(例如在.NET中使用Wsdl.exe)。
為了自訂WSDL產生進程,你可以編寫一個SoapExtensionReflector類並在Web.config檔案中向WebMethods架構組件註冊。接著,當.asmx處理常式產生WSDL定義時,它將調用你的反射類,給了你自訂最終提供給用戶端的定義的機會。如果你要瞭解更多的編寫SoapExtensionReflector類的方法,請查看SoapExtensionReflectors in ASP.NET Web Services。
你可以使用兩種不同的技術來繞過WSDL產生進程。第一種是你可以在虛擬目錄種為用戶端的訪問提供靜態WSDL文檔並在Web.config檔案中刪除文檔產生部分,如下所示:
<configuration> <system.web> <webServices> <protocols> <remove name="Documentation"/> </protocols> ...
另一種稍微自動化的技術是使用[WebServicesBinding]標誌來指定實現WebMethod類的虛擬目錄中的靜態WSDL文檔的位置。你也必須使用[SoapDocumentMethod]標誌指定幫定到每個WebMethod實現的WSDL的名稱。有了這些後,自動化的WSDL產生進程將匯入你的靜態WSDL檔案並在它周圍封裝一個新的服務描述。如果你要瞭解這種技術的更多資訊,請查閱Place XML Message Design Ahead of Schema Planning to Improve Web Service Interoperability。
目前WSDL極難手動編寫,因為沒有很多的可用的WSDL編輯器。因此,自動的文檔/WSDL產生是WebMethods架構組件中有價值的一部分,很多開發人員將很長時間依賴它。
結論
ASP.NET的WebMethods架構組件提供了一條高效率建立Web服務的途徑。WebMethods把傳統.NET方法為支援HTTP、XML、XML Schema、SOAP和WSDL暴露為Web服務作業成為可能。WebMethods(.asmx)處理常式自動找出怎樣把輸入的SOAP訊息指派給適當的方法,這時它自動把輸入的XML元素序列化成相應的.NET對象。為了簡化與用戶端的整合,.asmx處理常式也提供了產生人類可讀(HTML)和電腦可讀(WSDL)文檔的自動支援。
儘管WebMethods架構組件與自訂IHttpHandlers相比稍微有點限制,但是它也提供了強大的可擴充性模型,就是我們所知道的SOAP擴充架構組件。SOAP擴充允許你根據需要引入附加的功能。例如,微軟為.NET發布了Web Services Enhancements 1.0(WSE),它僅僅提供了一個SoapExtension類,該類為WebMethods架構組件引入了對幾種GXA規格的支援。如果你需要瞭解編寫SOAP擴充的更多資訊,請參閱Fun with SOAP Extensions。