WCF的所有服务都会公开为契约(Contract)。契约与平台无关,是描述服务功能的标准方式。WCF定义了四种类型的契约。
1、服务契约(Service Contract)
服务契约描述了客户端能够执行的服务操作。
2、数据契约(Data Contract)
数据契约定义了与服务交互的数据类型。WCF为内建类型如int和string隐式地定义了契约;我们也可以非常便捷地将定制类型定义为数据契约。
3、错误契约(Fault Contract)
错误契约定义了服务抛出的错误,以及服务处理错误和传递错误到客户端的方式。
4、消息契约(Message Contract)
消息契约允许服务直接与消息交互。消息契约可以是类型化的,也可以是非类型化的。如果系统要求互操作性,或者遵循已有消息格式,那么消息契约会非常有用。WCF开发者极少使用消息契约。
服务契约
- [ServiceContract]
- interface IMyContract
- {
- [OperationContract]
- string MyMethod(string text);
- //不会成为契约的一部分
- string MyOtherMethod(string text);
- }
- class MyService:IMyContract
- {
- public string MyMethod(string text)
- {
- return "Hello "+text;
- }
- public string MyOtherMethod(string text)
- {
- return "Cannot call this method over WCF";
- }
- }
ServiceContract特性可以将一个CLR接口映射为与技术无关的服务契约。ServiceContract特性公开了CLR接口(或者类)作为WCF契约。如果接口没有标记ServiceContract特性,WCF客户端则无法访问它。这一特点遵循了面向服务的一个原则,即明确的服务边界。为满足这一原则,所有契约必须明确要求:只有接口(或者类)可以被标记为ServiceContract特性,从而被定义为WCF服务,其他类型都不允许。
在标记为ServiceContract特性的服务契约中,必须使用OperationContract特性显示表明哪些方法需要暴露为WCF契约中的一部分。WCF只允许将OperationContract特性应用到方法上,而不允许应用到同样属于CLR概念的属性、索引器和事件上。此外,契约操作不能使用引用对象作为参数,只允许使用基本类型或数据契约。
应用ServiceContract特性
一个单独的类通过继承和实现多个标记了ServiceContract特性接口,可以支持多个契约。
服务类还有一些实现上的约束,我们要避免使用带参构造函数,因为WCF只能使用默认构造函数。
应尽量避免将ServiceContract特性直接应用到服务类上,而应该定义一个单独的契约,这有利于在不同场景下使用契约。
名称与命名空间
可以为契约定义命名空间。契约的命名空间具有与.NET编程相同的目的:确定契约类型范围,以降低类型的冲突几率。可以使用ServiceContract类型的Namespace属性设置命名空间:
- [ServiceContract(Namespace="MyNamespace")]
- interface IMyContract
- {...}
若非特别指定,契约的默认命名空间为http://tempuri.org。对外服务的命名空间通常使用公司的URL;至于企业网(Intranet)内部服务的命名空间,则可以定义有意义的唯一名称,例如MyApplication。
在默认情况下,契约公开的名称就是接口名。但是也可以使用ServiceContract特性的Name属性为契约定义别名,从而在客户端的元数据(Metadata)中公开不同的名称:
- [ServiceContract(Name="IMyContract")]
- interface IMyOtherContract
- {...}
相似的,操作公开的名称默认为方法名,但我们同样可以使用OperationContract特性的Name属性设置别名,从而公开不同的操作名:
- [ServiceContract]
- interface IMyContract
- {
- [OperationContract(Name="SomeOperation")]
- void MyMethod(string text);
- }