网络安全 频道

ASP.NET Web服务如何工作?

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

0
相关文章