使用 Windows Communication Foundation 进行基于架构的开发
Christian Weyer & Buddhike de Silva
“如果我有八个小时砍倒一棵树,我会花六个小时将斧头磨快”Abraham Lincoln 说。这个观点同样适用于软件工程的不同阶段。拥有一个考虑全面的设计就是多数软件成功案例背后的秘密。对于设计通信系统(如 Web 服务 (WS))来说,情况更是如此。应该密切注意用于通信的正式界面。此界面指明您的系统的可用性和互操作性。因此,在生命周期的早期阶段设计此界面(也称为约定)很重要。在本文中,我们将介绍如何首先为基于 Windows Communication Foundation (WCF) 的服务设计和建立约定,主要侧重于 Web 服务。WS 约定中存在两种主要方法 -- 代码优先、约定优先开发 和架构优先、约定优先开发。我们主要介绍后者。
什么是约定优先开发?
约定优先设计和开发已不是什么新鲜事物了,由 Bertrand Meyer 作为其 Eiffel 编程语言设计的一部分正式引入,自 19861、2 开始出现在各种技术出版物种。因此,从老式的工具/技术角度了解约定可能有助于理解它为什么有用。
虽然如今计算机可以执行很多操作,从简单的算术到控制绕我们的地球运行的卫星,但自 19 世纪发明计算机以来,输入-输出计算机的根本观念从来没有改变过。因此,软件工程师仍然在继续编写函数,可以接受一些输入、执行某些操作然后输出一些内容。然后从其他位置使用这些函数。函数的约定可定义该函数的期望值和承诺。换句话说,函数的输入参数可视为其期望值,返回值可视为其承诺。使用此函数的用户只需要了解使用此函数的约定。有关此问题的一个典型示例是 C++ 头文件。当您要在另一个 C++ 库中调用某函数时,您对查看实现不感兴趣 -- 实际在大多数情况下,您根本不会访问实现。纯文本标头文件已显示了调用该函数时您和您的编译器需要的全部内容,以及实现此函数时您将获得的结果。
COM 和 ActiveX 中的类型库文件以及 C# 中的界面通常可看做其他形式的约定。因为约定是一种根据抽象数据类型为软件组件定义正式、准确、可验证的界面规范的方式,所以有一种先创建约定的自然倾向。这就是为什么几乎每个 C/C++ 编程人员开始编写程序时都会首先编写头文件。
WS 中的约定也不例外。作为 WS 开发人员,您的目标是作为 Web 服务共享您的输入/输出系统 – 很可能横平台边界进行。我们确信您以前曾多次听说过 Web 服务用户不用担心实现细节。可以访问您的约定足以应对使用该约定的其他人。由于 Web 服务是独立于平台的,所以我们使用诸如 Web 服务定义语言 (WSDL) 和 XML 架构 (XSD) 等可互操作、基于标准的结构来定义约定。建模约定涉及建模数据、消息和 Web 服务界面。
首先,建模用于在客户端和服务之间传递数据的数据约定(即数据结构)。数据约定可以是简单类型或基元类型,如 string、integer、double,也可以是复杂类型或特定域类型,如 Product、Employee 或 Itinerary。
RPC/Encoded 样式使用在架构中定义的类型来定义 WSDL 消息的组成部分。这样,很难根据该架构验证整个 SOAP 体,因为只有一部分表示架构中定义的内容,其它则来自于 WSDL。而且也只能根据由 SOAP 1.1 规范定义的第 5 部分编码规则对 SOAP 主体内容进行编码。虽然这种样式是合法的,但却与 WS-I 不兼容。
RPC/Literal 样式与 RPC/Encoded 样式非常相似。然而,与 RPC/Encoded 样式不同的是,它不能对 SOAP 主体进行编码。虽然这种样式与 WS-I 兼容,但是很难进行验证。
Document/Literal 使用元素定义 WSDL 消息的组成部分,并不对主体内容进行编码。这可以消除以前讨论的样式中存在的两个主要问题。因而这种样式成为普遍接受的 WS-I 兼容样式。
Document/Literal/Wrapped 样式是由 Microsoft 引入的。这种样式与 Document/Literal 样式相同,但它还可以封装由操作名称在元素内部创建的元素的内容。掌握主体中的操作名称可以更容易从非 HTTP 端点调度消息。但更重要的是,它还有助于与在元素内部只要求一个子元素的 WS-I 标准兼容。
Web 服务通常通过交换 SOAP 消息3与其客户端交互。建模这些消息约定是约定优先开发的第二步。您如何建模取决于您喜欢使用哪种 SOAP 消息格式:
- RPC/Encoded
- RPC/Literal
- Document/Literal
- Document/Literal/Wrapped
还有另一种格式,称为 Document/Encoded,但是找到使用它的实现非常困难。在本文中,我们只重点讨论 Document/Literal/Wrapped,因为这种样式最常用,而且与服务互操作性组织 (WS-I) 兼容。
定义消息约定包含两个方面。首先,应定义 SOAP 主体的结构。您可以使用 XSD 执行此操作,而且您还可以使用您在上一步中定义的数据约定。消息约定的另一个方面是定义 SOAP 标头的结构。消息的标头在 WSDL 中定义。常见做法是使用在第一步中建模的数据约定来定义这些标头中包含哪些内容。
一旦拥有了数据和消息约定,您可以通过在服务中定义一个或多个可用的操作来建模您的界面。操作约定可以使用在第二步中建模的消息约定来定义在该操作期间交换哪些消息。
除三种主要约定类型(数据、消息和界面合同)之外,Web 服务约定也包含一项策略,多个绑定和端点。图 1 总结了使用哪个 WSDL/架构构造表示 Web 服务约定中的不同产物。
图 1 WSDL 和 XSD 架构使用情况
代码优先与架构优先
正如简介中所述,有两种方式可以建立约定模型 - 代码优先 和架构优先。了解这两种方式很重要,这样才能选择哪种方式满足您的需求。
在代码优先这种模式中,您可以使用由不同的 Web 服务堆栈(WCF、ASMX、JAX-WS 等)提供的功能强大的声明性约定编程构造。这样,您可以在您喜欢的编辑器中使用您喜欢的编程语言建立其模型。因此不用学习 WSDL 和 XML 架构构造,您也可以使用已熟悉的编程构造和数据类型。基本 WS 堆栈负责繁重的工作,以其本机形式(WSDL 和 XSD)生成 WS 约定。这些声明性编程构造也使得从头开始整理新的 Web 服务或作为服务公开现有实现变得更轻松。
如果不了解用于表示您所建模产品的基本 WSDL/XSD 构造就应用此便捷性,可能会导致不易察觉的问题。的确,这与上述如果不具备 WSDL 和 XSD 知识也可以部署您的约定的观点相矛盾。但是,不幸地的是疏忽了代码优先概念。我们尽量从 .NET 开发人员的角度来了解原因所在。
在您使用代码的同时,仍然可以使用 .NET 类型系统建模对象图。例如,在使用代码优先方法时,可以使用 System.Data.DataSet 或 System.DateTimeOffset 等 .NET 特性。这些类型可以使用 XML 明确表示(它们是可序列化的 XML)。但是非 .NET 客户端不可以访问同样的类型。
循环图也是一个很好的示例。如上所述,使用代码优先方法的同时,您仍可以使用面向对象的方法。因此,您倾向于建模对象图,并且那些图形可以具有良好的循环引用。考虑为以下数据结构应用循环引用:
public class OrderItem
{
public Order Order { get; set; }
}
public class Order
{
public List<OrderItem> Items { get; set; }
}
一个 Order 具有一个 OrderItems 列表并且每个 OrderItem 具有一个返回父 Order 的引用。如果您尝试使用 XML 中表示它们,XML 将不提供对象标识的标记,最后结果可能类似于图 2 中无限循环的情况。
图 2 在 XML 中使用循环引用表示对象图
<Order>
<Items>
<OrderItem>
<Order>
<Items>
<OrderItem>
...
</OrderItem>
</Items>
</Order>
</OrderItem>
</Items>
</Order>
XML 文档的实际层次结构和对象图中的图形模型之间的区别是导致这种情况的原因。但不妙的是,当您使用代码优先方法时这些区别不易察觉到。要想解决该问题,您需要通过 DataContractAttribute 中的 IsReference 属性启用 DataContractSerializer 中的引用跟踪。但接下来您将遇到其他一系类问题:首先,您不能验证 XML 文档的架构是否使用了标准架构验证 API;其次,序列化程序使用的标准引用跟踪机制基于 SOAP 1.1 规范中定义的第 5 部分中的编码规则。在 WS-I 规范中指定了一条标准,以上规则不适用于文档/文本样式的信息。
尽管代码优先方法中存在以上问题,但使用 WCF 编程构造仍然比使用 WSDL/XSD 构造简单,只要您对这两种构造是如何相互映射以及 WCF 序列的工作原理略知一二。虽然该文章没有详细讲述代码优先约定优先方法,但通过以下图表,您可以深刻了解最常用的 WCF 约定编程构造和 WSDL/XSD 构造之间的关系。
图 3 常用 WCF 中的声明性编程构造和 WSDL/架构构造之间的映射
代码优先设计的替代是架构优先 设计,该设计直接使用 WSDL 和 XSD 进行建模。在处理本地构造时,该设计是建模 WS 构造的一个更加自然的方法。使用 WSDL 和 XSD,您可以更倾向借助以 XML 为中心建模您的构造,从而可以消除代码优先方法中的很多不足之处。
但是,您需要非常了解 WSDL 和 XSD 才可以使用此方法。另外,这两种构造是有联系的,您不能完全将精力放在 WSDL 或 XSD 上。例如,在架构优先方法中,有时您将必须从您的架构中生成代码以使用编程方式操纵数据结构。当今推出的不同的 WS 堆栈为此操作提供了工具(在文章的稍后部分我们将介绍 WCF 可以使用的工具)。然而,由于 XML 架构规范比较庞大,这些工具经常只支持架构构造的子集。所以,如果在您的架构中使用这些不支持的构造,您仍可能遇到互操作性方面的问题。此外,在许多工具包中,您建模的 XSD 限制等特定事物中没有等效声明,所以可能在代码生成期间消失。
在代码优先方法中,您编写代码并且使用您的工具包为您生成 WSDL/XSD。所以,当您在代码中更改内容时,它将自动在生成的架构中反映出来。在架构优先方法中,如果不进行正确更改且没有团队中经过培训的开发人员,WSDL 和 XSD 将黯然失色。此外,您也可能需要这些工具建模您的 WSDL,因为您的 IDE 可能不具有这些现成的功能。
一般而言,代码优先和架构优先各有其优缺点。架构优先方法的优点尤其体现在方案中,因为您需要在方案中使用现有的架构,而您可能已在开发生命周期的非常早期的阶段以与利益相关者达成共识为目的对它们进行了建模。这是在政府和银行环境中常见的情况。如果您正在构建符合现有行业标准(例如,开放式旅游联盟 (OTA) )的应用程序,您可能还需要使用现有的架构。这两个约定定义方法的选择还应根据可供您的团队使用的方案、资源以及团队的技能。例如,如果您正在构建不需要支持在其他平台上运行的客户端的 WCF 服务,则您可能不需要考虑架构优先方法。同样,如果您非常熟悉约定编程构造、十分了解序列化过程且能够侧重于层次结构(而不是对象图),则您可以按照代码优先的方法并得到同样的结果。
因此,如果您决定采用架构优先方法,则将在本文的其余部分中向您介绍如果将其用于 WCF 服务。
架构优先方法说明
架构优先方法包含 5 个不连续步骤,如图 4 所示。
图 4 架构优先、约定优先开发过程
我们已在本文开头对前三个步骤进行了讨论。因此,让我们仅对它们进行一下总结,然后转到下几个要点。
**步骤 1 对数据进行建模:**使用 XML 架构对用于在您的服务和客户端之间传输数据的数据结构进行建模。可使用 Visual Studio XSD 编辑器或类似工具,例如 Altova XmlSpy 或 Liquid XML Studio。
**步骤 2 对消息进行建模:**如前所述,在此步骤中,您使用 XML 架构对消息结构进行建模。在此,您将可能使用在步骤 1 中建模的数据结构。
**步骤 3 对接口进行建模:**在此步骤中,您将通过定义其操作来对接口约定进行建模。但是,与之前的步骤不同,在此步骤中您必须使用 WSDL(而不是 XML 架构)。WSDL 编辑不可在 Visual Studio 中使用,但可在某些产品中使用,例如 Altova XmlSpy。
**步骤 4 生成代码:**对您的数据、消息和操作进行建模后,就该生成代码以用您喜欢的编程语言表示那些产物。以下两个部分将介绍 WCF 开发人员如何使用目前可用的工具生成代码。
**步骤 5 重复执行约定设计和代码生成:**很难一蹴而就。设计完约定后,您可能希望多次对其进行重构,直到发现所需的最合适的结构。
使用现成的 WCF 工具进行架构优先、约定优先开发
为了演示此方案,让我们构建一个简单的、用来检索主机中活动进程列表的 Web 服务。首先是数据约定,我们对两个复杂类型进行建模。
- 复杂类型 process 表示主机中的一个进程。
- 复杂类型 processList 表示由 process 类型定义的进程列表。
然后我们对这两个元素和 exploreResponse 进行建模以提炼输入/输出消息的正文。正如先前所述,为了实现与 WS-I 兼容,您必须确保您的消息正文在 soap:body 元素内部只有一个子元素。WCF 和 ASMX 都通过创建使用操作名称的包装元素来确保这种情况。如果用于对消息进行建模的命名约定不同于 WCF 标准,则代码生成工具将为请求和响应生成 MessageContract 类。我们使用 WCF 命名约定对消息元素进行命名,因此,稍后在此进程中生成代码时将有一个简单的对象模型。
最后,我们使用外部工具对 WSDL 进行建模。在这种情况下,我们使用 Altova XML Spy 帮助我们完成。
图 4、5 和 6 分别包含上述数据、消息和接口约定定义。
图 4 Data.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ns1="http://schemas.thinktecture.com/contractfirst/2009/07/data"
targetNamespace="http://schemas.thinktecture.com/contractfirst/2009/07/data"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
>
<xs:complexType name="process">
<xs:sequence>
<xs:element name="pid" type="xs:int"/>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="processList">
<xs:sequence>
<xs:element name="process" type="ns1:process" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
图 5 Messages.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:data="http://schemas.thinktecture.com/contractfirst/2009/07/data"
xmlns:ns1="http://schemas.thinktecture.com/contractfirst/2009/07/"
targetNamespace="http://schemas.thinktecture.com/contractfirst/2009/07/"
elementFormDefault="qualified">
<xs:import namespace="http://schemas.thinktecture.com/contractfirst/2009/07/data"
schemaLocation="data.xsd"/>
<xs:element name="explore">
<xs:complexType>
<xs:sequence>
<xs:element name="hostname" type="xs:string" nillable="true"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="exploreResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="processes" type="data:processList" nillable="true"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
图 6 ProcessExplorerService.wsdl
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="https://schemas.xmlsoap.org/wsdl/"
xmlns:soap="https://schemas.xmlsoap.org/wsdl/soap/"
xmlns:http="https://schemas.xmlsoap.org/wsdl/http/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="https://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="https://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://schemas.thinktecture.com/contractfirst/2009/07/"
xmlns:soap12="https://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:msg="http://schemas.thinktecture.com/contractfirst/2009/07/"
xmlns:ns="http://schemas.thinktecture.com/contractfirst/2009/07/data"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
targetNamespace="http://schemas.thinktecture.com/contractfirst/2009/07/">
<wsdl:types>
<xs:schema targetNamespace="http://schemas.thinktecture.com/contractfirst/2009/07/"
elementFormDefault="qualified">
<xs:import schemaLocation="messages.xsd"/>
</xs:schema>
</wsdl:types>
<wsdl:message name="exploreRequestMessage">
<wsdl:part name="parameters" element="msg:explore"/>
</wsdl:message>
<wsdl:message name="exploreResponseMessage">
<wsdl:part name="parameters" element="msg:exploreResponse"/>
</wsdl:message>
<wsdl:portType name="processExplorer">
<wsdl:operation name="explore">
<wsdl:input wsaw:Action="http://schemas.thinktecture.com/contractfirst/2009/07/explore"
message="tns:exploreRequestMessage"/>
<wsdl:output wsaw:Action="http://schemas.thinktecture.com/contractfirst/2009/07/exploreResponse"
message="tns:exploreResponseMessage"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="processExplorerHttpBinding" type="tns:processExplorer">
<soap12:binding style="document" transport="https://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="explore">
<soap12:operation
soapAction="http://schemas.thinktecture.com/contractfirst/2009/07/explore"
soapActionRequired="true"/>
<wsdl:input>
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap12:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ProcessExplorerService">
<wsdl:port name="processExplorerPort" binding="tns:processExplorerHttpBinding">
<soap12:address location="http://localhost/processexplorer"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
准备好约定后,我们可以启动 Visual Studio 2008 命令提示符并使用 svcutil.exe 为 WCF 生成 C# 代码:
svcutil -noconfig -serializer:datacontractserializer -d:../ -
namespace:*,Thinktecture.Samples.ProcessExplorerService
ProcessExplorerService.wsdl Messages.xsd Data.xsd
Svcutil.exe 主要用于生成客户端代码。与其前身 wsdl.exe 不同的是该版本不具有生成服务端框架的选项。因此,您会发现生成的代码中包含客户端代理代码,该代码在服务端实施中并不是必需的。对于服务实施,您需要从生成的代码中删除这些不相关的代码类型。在我们的示例中,我们通过从生成的代码中删除 processExplorerClient 和 processExplorerChannel 类来实现这一操作。实现上述操作后,您可以仅实施生成的接口类型 processExplorer,如随附的示例解决方案中的 ProcessExplorerService1 项目所示。
最后,在承载服务之前,您必须调整 ServiceMetadataBehavior 以关闭自动生成 WSDL 并将 WCF 的元数据生成运行时指向静态 WSDL 文件。以下示例指定了 WCF 配置中的外部元数据位置:
<serviceMetadata httpGetEnabled="true"
externalMetadataLocation="..\contracts\processexplorerservice.wsdl"/>
正如您可能注意到的那样,在实际应用程序中使用此方法进行架构优先开发可能有点困难。所创建的 WSCF.blue,Web service Contract First (WSCF) 工具的后续产品,旨在弥补这一缺陷。
WSCF.blue 概述
WSCF.blue 是免费的 Visual Studio 2008 加载项。其主要功能是能够在您收藏的 IDE 内部进行架构优先、约定优先开发。您可以在 Visual Studio XML 架构编辑器或免费提供的工具(如,Liquid XML 编辑器)中建模数据和消息约定。您可能偏向于后者,因为 Visual studio 2008 中提供的架构编辑器提供的建模支持少于 Visual Studio 2005 中的编辑器提供的支持。准备好架构后,您可以使用 WSCF.blue 的 WSDL 生成向导建模服务接口。它提供了一种简单的方法,来建模接口操作以及隐藏实际 WSDL 构造的详细信息。可通过右键单击包含消息约定的 XSD 文件,然后从上下文菜单中选择“创建 WSDL 接口描述”来启动此向导,如图 7所示。
图 7 启动 WSDL 生成向导
此向导包括收集信息的几个步骤,这些信息是有关您希望在服务接口中包含的操作约定的信息。大部分步骤都很简单。不过,在步骤 2、3 和 4 中您需要注意几个方面。
在您从“解决方案资源管理器”中选择的用来启动向导的架构文件中定义的类型将用于 WSDL 建模。但是,如果其他 XSD 文件中包含其他类型,您还可以在步骤 2 中导入这些类型,如图 8 所示。
图 8 将其他架构文档导入向导
在步骤 3 中,建模您的操作。向导中还包含一个可以遍历您的消息约定元素并推断相应操作的功能。但是,此功能仅对利用向导的推断规则中使用的命名约定的消息有效,如图 9 所示。
图 9 接口中的添加或删除操作
在步骤 4 中,您可以将已建模的消息映射到请求和响应操作中。如果已经使用步骤 3 中的推断功能,向导将自动完成这个映射过程。您还可以在此步骤中定义请求和响应消息中的消息标头(图 10)。
图 10 定义操作中的输入/输出消息。
最后,完成此向导后,会将生成的 WSDL 文件添加到您的项目中。
现在已完成建模约定,您可以使用 WSCF.blue 代码生成工具生成您使用的项目语言版本的 WCF 代码。在“解决方案资源管理器”中右键单击 WSDL 文件,然后从上下文菜单中选择“生成 Web 服务代码”菜单项以启动代码生成工具(图 11)。
图 11 启动代码生成工具
代码生成对话框为您提供了各种代码生成选项。其中包括可在 svcutil.exe 中使用的大部分选项以及其他一些选项,例如:用于生成服务器端代码的“服务器端存根”选项;用于在不影响序列化的情况下,将架构中使用的 camel 大小写名称转换为 Pascal 大小写名称的“调整大小写”选项;以及用于为各个生成的 CLR 类型生成代码文件以表示相应的架构产物的“单独文件”选项(图 12)。图 13包含代码生成工具中可用选项的完整列表。
图 12 代码生成选项
图 13 WSCF.blue 代码生成选项
选项 | 说明 |
客户端代理 | 为服务使用者生成客户端代理。 |
服务端存根 | 为服务实施人员生成服务端代码。 |
公共属性 | 将生成的类成员公开为公共属性。 |
可序列化类 | 生成的类将使用 SerializableAttribute 加以修饰。 |
集合 | 使用 Collection<T> 类型表示集合类型。 |
List<T> | 使用 List<T> 类型表示集合类型。 |
数据绑定 | 生成要求将生成的类绑定到数据可绑定组件的代码。 |
顺序标识符 | 为每个使用的 DataMemberAttribute 生成 Order 属性。 |
异步方法 | 生成操作的异步版本并将 OperationContextAttribute.AsyncPattern 属性设置为 true 以告知 WCF 存在此类版本。 |
单独文件 | 每个生成的类都放在其各自的文件中。 |
调整大小写 | 在不影响序列化过程的情况下,使用 Pascal 大小写命名生成的类和其属性。 |
并发模式 | 指定为 ServiceBehaviorAttribute.ConcurrencyMode 属性生成的值。 |
实例上下文模式 | 指定为 ServiceBehaviorAttribute.InstanceContextMode 属性生成的值。 |
使用同步环境 | 指定为 ServiceBehaviorAttribute.UseSyncrhronizationContext 属性生成的值。 |
启用 WSDL 端点 | 将端点添加到服务以公开静态元数据文件。这对于希望在自承载服务中公开静态元数据文档至关重要。 |
目标文件名 | 输出文件的名称。如果启用"单独文件"选项,此参数将被弃用且类名称将被用作文件名。 |
目标命名空间 | 用于生成类型的 CLR 命名空间。 |
记住设置 | 记住最近使用的代码生成选项。 |
覆盖现有文件 | 指定允许 WSCF.blue 覆盖现有文件(而不是创建唯一的文件名)以解决冲突。有一点必须注意,您对生成的代码执行的任何自定义都将被覆盖。因此我们建议您通过局部类进行这样的修改。 |
本文介绍的 WSCF.blue 的发布版本(Beta 1,2009 年 7 月 25 日)尚不支持合并配置文件。因此,承载您的服务所需的配置将被发送到 output.config文件。根据需要,需要手动将此文件的内容移动到 web.config 或 app.config 文件。
准备好配置文件后,您可以继续将必要的实现添加到生成的服务类。
最后,您可以在 Visual Studio 中修改架构、使用 WSDL 生成向导中的 WSDL 往返功能更改约定并重新生成代码。
其他功能
WSCF.blue 已经以开源项目的形式发布,所在位置为 wscfblue.codeplex.com。当前的 Beta 版存在某些限制,可能会限制您实施基本的、但也是最常用的 Web 服务。例如,WSDL 生成向导当前仅支持基本的 http 绑定。此外,当前 WSCF.blue 中的代码生成功能仅生成 XmlSerializable类(而不生成 DataContractSerializable类)以支持更广范的架构构造。CodePlex 站点提供了已知问题的完整列表和工具的路线图。
有关如何使用 WSCF 的详细步骤,请访问 thinktecture.com/resourcearchive/tools-and-software/wscf/wscf-walkthrough。虽然该文档基于 WSCF 0.6,但是以上介绍的步骤同样适用其他版本
结论
通过 Web 服务基于架构、约定优先建模,您可以利用以 XML 为中心的构想建模约定。此过程可以让您重点处理普遍接受的类型和能够以 XML 格式表示的分层数据结构。工具支持对 Web 服务平台的成功至关重要。WSCF.blue 可以扩展由 WCF 提供的现有工具,以便简化 WCF 开发人员基于架构、约定优先的开发。
Christian Weyer是 thinktecture 的共同创始人之一,也是一位首席架构师,曾多年使用 Java、COM、DCOM、COM+、Web 服务、WCF 和其他技术进行分布式应用程序的建模和实现。Christian 是适用于 .NET 的典型 Web 服务约定优先工具的最早发明者。您可以通过 thinktecture.com/staff/christian 与他联系。
Buddhike de Silva是一名澳大利亚工程师。在移民澳大利亚之前,他曾是 thinktecture 的首席工程师。Buddhike 多年来一直在设计和实施分布式应用程序,同时他也是 WSCF/WSCF.blue 项目的长期撰稿人。您可以通过 http://blogs.thinktecture.com/buddhike 与他联系。
1* 根据约定设计*,技术报告 TR-EI-12/CO,Interactive Software Engineering Inc., 1986。
2 http://se.ethz.ch/~meyer/publications/computer/contract.pdf
3 RESTful 服务无论如何会通过交换标准的 HTTP 邮件与其客户端通信并遵循完全不同的模式。