通常,除非你已经掌握了XML、XSD、SOAP和WSDL并且原意承担直接处理它们的负担,最好不要专注于Web服务所需要的WebMethods框架组件。它提供了大多数Web服务端点(endpoints)所需要的基本服务,以及能把框架组件进行"弯曲"来适合你的精确的需要的一些有趣的可扩充能力。本文是基于这种假定讨论WebMethods如何工作的内部信息。如果你不太了解XML Schema和SOAP,可以参阅Understanding XML Schema和Understanding SOAP。
当你使用Visual Studio .NET建立一个新的Web服务项目时,它通常使用"双文件"技术,把源文件与引用它的.asmx文件分开。集成开发环境(IDE)隐藏了这些文件,但是你可以点击"解决方案浏览器"工具条上的Show All Files(显示所有文件),你会发现项目中的每个Web服务类都有两个文件。实际上,Visual Studio .NET并不支持.asmx文件的高亮度提醒或IntelliSense。有了Web项目后,Visual Studio .NET也处理建立虚拟目录并自动把部件编译到虚拟目录的bin目录中。
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)); }}
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")]
[XmlType(Namespace="http://example.org/security")][XmlRoot(Namespace="http://example.org/security")]public class UsernameToken : SoapHeader { public string username
using System;using System.Web.Services;using System.Web.Services.Protocol
[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。
如上所示,指出WebMethod如何工作必须了解下层串行化引擎和它的多种选项。串行化引擎的优点是它隐藏了所有的通常在编写自定义处理程序中需要的下层XML API代码。但是,尽管大多数开发者发现这是有正面意义的,有一些开发者认为它是一个缺陷,因为它们仍然希望在WebMethod实现中手动包装SOAP消息。要了解如何实现这种混合的途径的详细信息,请参阅Accessing Raw SOAP Messages in ASP.NET Web Services。
为了自定义WSDL生成进程,你可以编写一个SoapExtensionReflector类并在Web.config文件中向WebMethods框架组件注册。接着,当.asmx处理程序生成WSDL定义时,它将调用你的反射类,给了你自定义最终提供给客户端的定义的机会。如果你要了解更多的编写SoapExtensionReflector类的方法,请查看SoapExtensionReflectors in ASP.NET Web Services。
另一种稍微自动化的技术是使用[WebServicesBinding]标志来指定实现WebMethod类的虚拟目录中的静态WSDL文档的位置。你也必须使用[SoapDocumentMethod]标志指定帮定到每个WebMethod实现的WSDL的名称。有了这些后,自动化的WSDL生成进程将导入你的静态WSDL文件并在它周围包装一个新的服务描述。如果你要了解这种技术的更多信息,请查阅Place XML Message Design Ahead of Schema Planning to Improve Web Service Interoperability。