.asmx处理程序提供的功能之XML映射

将 XML映射到对象
在 WebMehod 处理程序确定了要调用的方法之后,它需要将 XML 消息反序列化为可在方法调用过程中提供的 .NET 对象。如同消息调度一样,该处理程序通过以下方法来实现上述目标:通过反射来检查该类,以便确定如何处理传入的 XML 消息。XmlSerializer 类在 System.Xml.Serialization 命名空间中自动完成 XML 和对象之间的映射。

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:申请域名网站空间、营销软件、网站建设、东阳网站维护、网站推广。

XmlSerializer 使将任何公共的 .NET 类型映射到 XML 架构类型成为可能,在建立了这样的映射之后,它可以在 .NET 对象和 XML 实例文档之间自动映射(请参阅图 4)。目前,XmlSerializer 被限制于 XML 架构所支持的模型中,因此无法处理当今所有复杂的现代对象模型,例如,复杂的非树型对象图、双重指针等。不过,XmlSerializer 能够处理开发人员倾向使用的大多数复杂类型。

对于上面说明的 Add 示例,XmlSerializer 会将 x 和 y 元素映射为 .NET 双精度值,这些值随后会在调用 Add 时提供。Add 方法向调用方返回一个双精度值,该值随后将需要重新序列化为 SOAP 响应中的一个 XML 元素。

图 4. 将 XML映射到对象
XmlSerializer 还可以自动处理复杂的类型(除了上面描述的限制)。例如,下面的 WebMethod 计算两个 Point 结构之间的距离:

 
 
 
 
  1. using System; 
  2. using System.Web.Services; 
  3. public class Point { 
  4. public double x;  
  5. public double y; 
  6. [WebService(Namespace="urn:geometry")] 
  7. public class Geometry { 
  8. [WebMethod] 
  9. public double Distance(Point orig, Point dest) { 
  10. return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) + 
  11. Math.Pow(orig.y-dest.y, 2)); 

此操作的 SOAP 请求消息将包含一个 Distance 元素,该元素中包含两个子元素,一个叫做 orig,另一个叫做 dest,它们都应当包含 x 和 y 子元素,如下所示:

 
 
 
 
  1. < soap:Envelope  
  2. xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
  3. > 
  4. < soap:Body> 
  5. < Distance xmlns="urn:geometry"> 
  6. < orig> 
  7. < x>0< /x> 
  8. < y>0< /y> 
  9. < /orig> 
  10. < dest> 
  11. < x>3< /x> 
  12. < y>4< /y> 
  13. < /dest> 
  14. < /Distance> 
  15. < /soap:Body> 
  16. < /soap:Envelope> 

在本例中,SOAP 响应消息将包含一个 DistanceResponse 元素,该元素包含一个双精度类型的 DistanceResult 元素:

 
 
 
 
  1. < soap:Envelope  
  2. xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
  3. > 
  4. < soap:Body> 
  5. < DistanceResponse  
  6. xmlns="urn:geometry"> 
  7. < DistanceResult>5< /DistanceResult>  
  8. < /DistanceResponse> 
  9. < /soap:Body> 
  10. < /soap:Envelope> 

默认的 XML映射将方法的名称用作请求元素的名称,将参数的名称用作请求元素的子元素的名称。每个参数的结构都取决于类型的结构。公共字段和属性的名称只是映射到子元素(在本例中是 Point 中的x 和 y)。在默认情况下,响应元素的名称是请求元素的名称后面加上 "Response"。响应元素也包含一个子元素,名称是请求元素的名称后面加上 "Result"。

您可以通过使用大量的内置映射属性从标准的 XML 映射中解放出来。例如,可以使用 [XmlType] 属性来自定义类型的名称和命名空间。可使用 [XmlElement] 和 [XmlAttribute] 属性来控制参数或类成员分别映射到元素或属性的方式。还可以使用 [SoapDocumentMethod] 属性来控制方法本身如何映射到请求/响应消息中的元素名称。例如,使用散布于下面程序片段中的多种属性检查如下版本的 Distance:

 
 
 
 
  1. using System; 
  2. using System.Web.Services; 
  3. using System.Web.Services.Protocols; 
  4. using System.Xml.Serialization; 
  5. public class Point { 
  6. [XmlAttribute] 
  7. public double x; 
  8. [XmlAttribute]  
  9. public double y; 
  10. [WebService(Namespace="urn:geometry")] 
  11. public class Geometry { 
  12. [WebMethod] 
  13. [SoapDocumentMethod(RequestElementName="CalcDistance", 
  14. ResponseElementName="CalculatedDistance")] 
  15. [return: XmlElement("result")] 
  16. public double Distance( 
  17. [XmlElement("o")]Point orig, [XmlElement("d")]Point dest) { 
  18. return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) + 
  19. Math.Pow(orig.y-dest.y, 2)); 

这个版本的 Distance 希望传入具有如下外观的 SOAP 消息:

 
 
 
 
  1. < soap:Envelope  
  2. xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
  3. > 
  4. < soap:Body> 
  5. < CalcDistance xmlns="urn:geometry"> 
  6. < o x="0" y="0" /> 
  7. < d x="3" y="4" /> 
  8. < /CalcDistance> 
  9. < /soap:Body> 
  10. < /soap:Envelope> 

而且,它将生成一个如下所示的 SOAP 响应消息:

 
 
 
 
  1. < soap:Envelope  
  2. xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
  3. > 
  4. < soap:Body> 
  5. < CalculatedDistance xmlns="urn:geometry"> 
  6. < result>5< /result> 
  7. < /CalculatedDistance> 
  8. < /soap:Body> 
  9. < /soap:Envelope> 

.asmx 处理程序使用 SOAP document/literal 样式来实现和描述上面显示的默认映射。这意味着该 WSDL 定义将包含用来描述 SOAP 消息中所使用的请求和响应元素的字面上的 XML 架构定义(例如,不使用 SOAP 编码规则)。

.asmx 处理程序还可以使用 SOAP rpc/encoded 样式。这意味着 SOAP 正文中包含一个 RPC 调用的 XML 表示形式,而且参数都使用 SOAP 编码规则(例如,不需要 XML 架构)进行了序列化。为了实现这个目标,可以使用 [SoapRpcService] 和 [SoapRpcMethod] 属性,而不使用 [SoapDocumentService] 和 [SoapDocumentMethod] 属性。有关这些样式之间的区别的更多信息,请查看 Understanding SOAP。

正如您所看到的一样,可以完全自定义给定方法映射到 SOAP 消息的方式。XmlSerializer 提供一个功能强大的序列化引擎,以及许多我们在本文中没有时间进行讨论的功能。有关 XmlSerializer 如何工作的更多信息,请查看 Moving to .NET and Web Services。在我的每月 MSDN Magazine 的 XML Files 专栏(可在联机存档中查看专栏列表)中,我还介绍了 XmlSerializer 的许多不易察觉的细微差别。

除了对参数的反序列化进行处理以外,.asmx 处理程序还能够对 SOAP 头进行反序列化/序列化。SOAP 头的处理方法与参数不同,因为它们通常被视为带外信息,并未直接关联到某个特定的方法。因此,SOAP 头的处理通常是通过侦听层完成的,从而使得 WebMethod 完全无须对 SOAP 头进行处理。

但是,如果您希望亲自处理 WebMethod 中的头信息,则必须提供一个从 SoapHeader 派生的 .NET 类,此类代表该头的 XML 架构类型(遵循上面描述的同一映射准则)。然后定义该类型的成员变量,以便让其充当头实例的占位符。***,批注每个需要访问该头的 WebMethod,以便指定您想要到达的字段的名称。

例如,考虑下面的 SOAP 请求,其中包含有一个用于进行身份验证的 UsernameToken 头:

 
 
 
 
  1. < soap:Envelope  
  2. xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
  3. > 
  4. < soap:Header> 
  5. < x:UsernameToken xmlns:x="http://example.org/security"> 
  6. < username>Mary< /username> 
  7. < password>yraM< /password> 
  8. < /x:UsernameToken> 
  9. < /soap:Header> 
  10. < soap:Body> 
  11. < CalcDistance xmlns="urn:geometry"> 
  12. ... 

为了使 .asmx 处理程序能够反序列化该头,首先需要定义一个表示隐含的 XML 架构类型的 .NET 类(注:如果您实际上已经知道了该头的 XML 架构,则可以使用 xsd.exe /c 来生成该类)。在本例中,相应类的外观如下所示:

 
 
 
 
  1. [XmlType(Namespace="http://example.org/security")] 
  2. [XmlRoot(Namespace="http://example.org/security")] 
  3. public class UsernameToken : SoapHeader { 
  4. public string username; 
  5. public string password; 

接着,只需在 WebMethod 类中定义一个用来保存头类的实例的成员变量,并用 [SoapHeader] 属性批注 WebMethod,如下所示:

 
 
 
 
  1. using System; 
  2. using System.Web.Services; 
  3. using System.Web.Services.Protocols; 
  4. [WebService(Namespace="urn:geometry")] 
  5. public class Geometry { 
  6. public UsernameToken Token; 
  7. [WebMethod] 
  8. [SoapHeader("Token")] 
  9. public double Distance(Point orig, Point dest) { 
  10. if (!Token.username.Equals(Reverse(Token.password))) 
  11. throw new Exception("access denied"); 
  12. return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) + 
  13. 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 响应,如下所示:

 
 
 
 
  1. < soap:Envelope  
  2. xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
  3. > 
  4. < soap:Body> 
  5. < soap:Fault> 
  6. < faultcode>soap:Server< /faultcode>     
  7. < faultstring>Server was unable to process request. --> access denied< /faultstring> 
  8. < detail /> 
  9. < /soap:Fault> 
  10. < /soap:Body> 
  11. < /soap:Envelope> 

如果您希望对 SOAP Fault 元素进行更多的控制,则还可以显式引发 SoapException 对象,以便指定所有的 SOAP Fault 元素细节,例如,faultcode、faulstring、faultactor 和 detail 元素。有关更多信息,请查看 Using SOAP Faults。

正如您所看到的一样,要知晓 WebMethod 如何工作必须了解基础序列化引擎及其各种选项。序列化引擎的好处在于,它隐藏了所有的基础 XML API 代码,而在自定义处理程序中,您通常必须编写这些代码。尽管多数开发人员发现这很好,但是,有一些开发人员却认为它是一个缺陷,因为他们仍希望亲自处理 WebMethod 实现中的原始 SOAP 消息。

本文题目:.asmx处理程序提供的功能之XML映射
浏览地址:http://www.shufengxianlan.com/qtweb/news23/306423.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联