这篇内容主要讲:什么是服务契约,如何定义,哪些操作接口是可用的,所使用的是什么数据类型,以及其他有关设计操作接口所需要设置的环境。
创建服务契约
服务暴露了一系列的操作。在WCF
应用程序中,通过创建方法并且在方法上标记OperationContractAttribute
属性来创建服务。然后,想要创建服务契约,需要将那些操作组合起来,将他们定义在一个接口中,并将接口标记上ServiceContractAttribute
属性,或者定义在一个类中,标记相同的属性。
没有被OperationContratAttribute
属性标记的方法不能够给外界提供WCF
服务。
这篇文章描述了创建服务的以下几点:
- 选择类还是接口
- 参数和返回值
- 所能使用的交换信息模式
- 明确操作的安全要求
- 操作的输入输出限制
选择类还是接口
类和接口都代表一组功能的组合,因此,无论是类还是接口都可以定义WCF
服务合约。然而,推荐使用接口,因为它直接模拟了服务合同。如果没有实现,接口仅仅只是定义了一组方法和签名。实现接口才实现了WCF
服务。
使用接口来定义服务的好处:
- 服务契约可以被其他服务契约所继承
- 一个类可以实现任意数量的服务契约
- 在保证契约接口不改变的前提下,可以修改服务契约的实现
- 可以实现新版本的接口和旧版本的接口,就客户端使用之前的版本,新版本客户端使用新服务接口
注:当继承其他服务契约的时候,不能够重写操作的属性,如
name
或者namespace
属性。如果需要这么做,就重新创建一个操作。
如,使用接口来定义服务契约,参考:How to: Create a Service with a Contract Interface
然而,也可以使用类定义服务契约并且同时实现操作。用类实现服务的好处就是简单方便。坏处就是不能被其他类所继承,并且只能实现一个服务契约。另外,任何对类或者方法的修改都会影响到服务契约,这有可能会妨碍未修改的客户端进行访问服务。更多内容请参考:Implementing Service Contracts
现在,应该明白使用接口和类定义服务的不同。下一步是确定服务端与客户端交换的数据类型。
参数和返回值
每个操作都有一个返回值和一个参数,即使返回类型为void
,然而,不像本地的方法一样,可以传送引用对象,服务契约不能给传递引用对象。而是用值得拷贝来代替传递引用对象的。
这一点很重要,因为每一个参数或返回值必须是可序列化的。这就是说,它必须能够从一个对象转换为一个字节流然后再转换为对象。
与.NET
框架中的大多类型一样,初始类型默认是可序列化的
注:操作签名中参数的名字是契约中的一部分,是区分大小写的。如果想要在本地使用参数名并且在契约中使用不同的参数名称,请参考:System.ServiceModel.MessageParameterAttribute
数据契约
如WCF
应用程序一样的面向服务的应用程序,是为了能够被微软和非微软平台的客户端都能够交互。为了使交互更加广泛,建议将数据契约的类型标记为DataContractAttribute
和DataMemberAttribute
属性,这是用来描述数据契约的也是服务契约中的一部分。
数据契约是选择式风格的契约:必须明确契约的属性数据才能够被序列化。数据契约与该成员的访问限制无关:私有数据成员可以被序列化或发送到其他地方也可以公开访问。WCF
处理底层的SOAP
消息,只要消息是可序列化的,就不需要考虑底层消息是如何传输的。
虽然通常的WCF
应用程序使用DataContractAttribute
和DataMemberAttribute
属性来创建数据服务,但是也可以使用其他的可序列化机制。标准的ISerializable,SerializableAttribute
和IXmlSerializable
机制都可以被底层的SOAP
消息所序列化处理的。如果数据类型需要的话可以使用更多的可序列化机制。更多有关数据类型可序列化的消息请参考Specifying Data Transfer in Service Contracts
映射参数和返回值到消息交换
服务操作是由一个基本的交换应用程序数据的消息交换来支持的,应用程序所需的数据支持某些标准的安全性、事务和会话相关的功能。因为这种情况下,一个服务操作的签名要求一定的基本消息交换模式(MEP
),可以支持数据传输的功能的操作要求。你可以在WCF
编程模型指定三种模式:请求/应答,单向,和双工消息模式。
请求/应答
请求/应答模式是指一个请求者(客户端)接受相关请求的应答模式。这是默认的模式,因为它支持多个参数传输到操作并且有一个返回值返回到客户端。如下Csharp
应用程序,接受一个字符串参数,返回一个字符串值。
[OperationContractAttribute]
string Hello(string greeting);
这个操作签名决定了底层消息的交换形式。如果不存在相关性,WCF无法确定操作的返回值。
注:即使你设置了不同的底层信息交互模式,服务操作的返回值为
void
也属于请求/应答模式。除非是客户端异步调用服务,否则客户端就会停止处理消息直到它接受到应答消息,即使消息是空或者其它值。
以下Csharp
代码是客户端接受空消息的响应。
[OperationContractAttribute]
void Hello(string greeting);
上面的这个例子,如果操作需要执行耗时操作就会降低客户端的性能和响应能力,但是当返回void
时有优势。最显著的就是SOAP
错误消息可以再响应消息中返回,SOAP
错误消息包含了服务器先关的错误信息。SOAP
错误消息包含在服务契约的FaultException<TDetail>
对象中发送给客户端,参数类型是指定的服务契约。这样更加方便的通知了客户端服务器的错误信息。更多有关异常,SOAP
错误消息,错误处理,参考Specifying and Handling Faults in Contracts and Services ,请求/应答服务和客户端,参考How to: Create a Request-Reply Contract,有关更多请求/应答模式的问题,参考Request-Reply Services
单向
如果WCF
服务的客户端不需要等待操作结束并且不需要处理SOAP
错误消息,这个操作可以被标记为单向(one-way
)消息模式。单向操作模式,是客户端调用操作并且