介紹
目前在微軟.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.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "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.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "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.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: ""
<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。
延伸閱讀
文章來源于領測軟件測試網 http://www.kjueaiud.com/