如果.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编码规则)。