第一次接触WCF,如有写的不对的地方有望大家指出来,谢谢!!

本篇文章主要说下WCF中的契约的种类、契约的种类、如何定义契约等内容。

契约是一种双边或多边的协议,是利益相关方就某个问题达成的一种共识,契约确保了服务的正常调用,客户端以契约的方式进行服务调用,而服务则需要照契约规定的方式提供服务。契约是服务提供的一组操作的描述,从功能上讲每个操作对应着某个具体的功能实现,以及调用这个操作的输入和输出;从消息交换层面上讲,每个操作定义了所采用的消息交换模式和消息本身的结构。

主要内容:

1.什么是契约?

2.契约有几种?他们都有什么用途

3.如何定义契约?

4.契约是独立于平台的么?

5.契约和以往哪种技术比较想像,又有什么不同

一、什么是契约?

任何一个分布式应用程序,它之所以能够互相传递消息,都是事先制定好数据交换规则的,这个规则正是交换数据的双方(比如服务器端和客户端)能彼此理解对方 的依据,WCF作为分布式开发技术的一种,同样具有这样一种特性。而在WCF中制定的的规则就被称之为契约(Contract),它是WCF的消息标准, 是任何一个wcf程序不可或缺的一部分。

二、契约的种类

在WCF中,契约分为四种,它们分别为:

1.服务契约

服务契约描述了暴露给外部的类型(接口或类)、服务所支持的操作、使用的消息交换模式和消息的格式。每个WCF服务必须实现至少一个服务契约。使用服务契约必须要引用命名空间System.ServiceModel 。服务契约中常用到的三个特性:

ServiceContractAttribute

该特性定义在类或接口上,用来描述一个相关操作的集合。ServiceContractAttribute特性还有如下的一些属性值可以设置:

Name:给服务契约定义一个名称,而不是使用接口或是类的类型名,在客户端添加服务引用时会用到。

Namespace:命名空间,默认值为http://tempuri.org。

CallbackContract:将另一个服务契约定义为回调契约,使得客户端可以接收服务端的异步消息。

ProtectionLevel:控制契约中发送给消息的保护方式是否需要被签名和加密。该属性为   System.Net.Security.ProtectionLevel枚举类型。

SessionMode:确定会话是否为公开服务契约的端点所支持。

ConfigurationName:服务的配置名称。

  1. [ServiceContract(Name="HelloWorld",Namespace="http://oec2003.cnblogs.com"]
  2. public interface IHelloWorldService
  3. {
  4.  
  5. }
OperationContractAttribute

用OperationContractAttribute标记的方法即为一个服务操作,简单的使用该特性就可以让一个方法加入到服务契约的操作队列中,可以被客户端所调用。该特性也有一些设置消息交换方式的属性。如下

Name:定义一个操作名称,而不是使用方法名称。

Action:该操作消息的动作标题。

ReplyAction:响应该操作消息的动作标题。

IsOneWay:设置该操作是否单向和没有回复,如果操作是单向的,将不支持ReplyAction。

ProtectionLevel:允许你控制特定的操作消息是否被保护,操作中的ProtectionLevel属性将覆盖服务契约中的ProtectionLevel。该属性为System.Net.Security.ProtectionLevel枚举类型。

IsInitiating:操作是否可以用来初始化会话。

IsTerminating:操作是否中止一个会话。

AsyncPattern:将服务操作定义为异步实现模式。

  1. [ServiceContract(Namespace="http://oec2003.cnblogs.com",Name="oec2003",
  2. ConfigurationName="IHelloWorldService")]
  3. public interface IHelloWorldService
  4. {
  5. [OperationContract(Name="oec2003SayHello",
  6. Action = "http://oec2003.cnblogs.com/IHelloWorldService/Hello",
  7. ReplyAction = "http://oec2003.cnblogs.com/IHelloWorldService/HelloReply")]
  8. string SayHello();
  9. }
MessageParameterAttribute

使用 MessageParameterAttribute 可以控制参数或返回值的名称。此属性对于已用 MessageContractAttribute 特性标记的参数无效。该特性只有一个Name属性,看如下代码:

  1. [ServiceContract(Namespace="http://oec2003.cnblogs.com",Name="oec2003",
  2. ConfigurationName="IHelloWorldService")]
  3. public interface IHelloWorldService
  4. {
  5. [OperationContract]
  6. [return: MessageParameter(Name = "responseString")]
  7. string SayHello([MessageParameter(Name = "string")]string meg);
  8. }

2.数据契约

使用数据契约必须引用System.Runtime.Serialization命名空间,在类型上使用DataContractAttribute可以创建数据契约,类型中的成员使用DataMember标记。代码如下:

  1. [DataContract]
  2. public class User
  3. {
  4. [DataMember]
  5. public int Age { get; set; }
  6. [DataMember]
  7. public string Name { get; set; }
  8. [DataMember]
  9. public string Email { get; set; }
  10. }
DataContractAttribute

DataContractAttribute特性定义在类型之上,类型包括类、结构、枚举但不包括接口。 DataContractAttribute特性不能被继承,即继承自有DataContractAttribute特性标记的类并不是数据契约,必须显 示使用DataContractAttribute标记才能成为数据契约。DataContractAttribute特性有IsReference、 Name和Namespace三个属性:

IsReference:bool类型,表示在进行序列化的时候是否保持对象现有的引用结构。

Name:名称。

Namespace:命名空间。

  1. [DataContract(IsReference=true,Name="MyUser",Namespace="http://oec2003.cnblogs.com")]
  2. public class User
  3. {
  4. [DataMember]
  5. public int Age { get; set; }
  6. [DataMember]
  7. public string Name { get; set; }
  8. [DataMember]
  9. public string Email { get; set; }
  10. }
DataMemberAttribute

使用DataMemberAttribute标记的类型成员才能成为数据契约的数据成员。这个和服务契约中的OperationContractAttribute类似。DataMemberAttribute特性有如下四个属性:

EmitDefaultValue:表明在数据成员的值等于默认值的情况下,是否还须要将其序列化到最终的XML中,默认值为true,表示默认值会参与序列化。

IsRequired:bool类型,表明属性成员是否是必须的成员,默认值为false。

Name:数据成员的别名。

Order:相应的数据成员在最终序列化的XML中出现的位置,默认是按字母顺序排列的。

  1. [DataContract(IsReference=true,Name="MyUser",Namespace="http://oec2003.cnblogs.com")]
  2. public class User
  3. {
  4. [DataMember(EmitDefaultValue=true,IsRequired=true,
  5. Name="Oec2003_Age",Order=1)]
  6. public int Age { get; set; }
  7. [DataMember(EmitDefaultValue = true, IsRequired = true,
  8. Name = "Oec2003_Name", Order = 2)]
  9. public string Name { get; set; }
  10. [DataMember(EmitDefaultValue = true, IsRequired = false,
  11. Name = "Oec2003_Email", Order = 3)]
  12. public string Email { get; set; }

3.消息契约

使用消息契约必须引用System.ServiceModel命名空间,消息契约和数据契约一样都是定义在数据类型上。和数据契约不同的是消息契约 更多的是关注数据成员在SOAP消息中的表示。定义一个消息契约需要用到MessageContractAttribute特性,另外还涉及到 MessageHeaderAttribute和MessageBodyMemberAttribute这两个特 性,MessageContractAttribute特性标记在类型上,MessageHeaderAttribute和 MessageBodyMemberAttribute特性标记在数据成员上。

  1. [MessageContract]
  2. public class MessageTest
  3. {
  4. [MessageHeader]
  5. public int Age { get; set; }
  6. [MessageHeader]
  7. public string Name { get; set; }
  8. [MessageBodyMember]
  9. public string Email { get; set; }
  10. }
MessageContractAttribute

通过在一个类型上使用MessageContractAttribute标记可以使之成为一个消息契约。MessageContractAttribute特性含有如下几个属性:

IsWrapped:是否为定义的主体成员(一个或者多个)添加一个额外的根节点。

WrapperName:根节点的名称。

WrapperNamespace:根节点的命名空间。

ProtectionLevel:表示保护级别,WCF中通过System.Net.Security.ProtectionLevel枚举定义消息的保护级别。一般有3种可选的保护级别:None、Sign和EncryptAndSign。

  1. [MessageContract(IsWrapped=false,WrapperName="MyMessage",
  2. WrapperNamespace="http://oec2003.com")]
  3. public class MessageTest
  4. {
  5. //省略
  6. }
MessageHeaderAttribute

使用MessageHeaderAttribute标记的数据成员将会出现在SOAP消息的头部,该特性包含下面几个属性:

Actor:为一个URI值,表示处理该报头的目标节点。

MustUnderstand:bool类型,表明Actor定义的节点是否必须理解并处理该节点。

Name:名称。

Namespace:命名空间。

ProtectionLevel:表示保护级别。

Relay:表明该报头是否需要传递到下一个SOAP节点。

  1. [MessageContract]
  2. public class MessageTest
  3. {
  4. [MessageHeader(Actor="http://oec2003.com/Age",MustUnderstand=true,Name="MyAge",
  5. Namespace="http://oec2003.com",Relay=true)]
  6. public int Age { get; set; }
  7. [MessageHeader]
  8. public string Name { get; set; }
  9. }
MessageBodyMemberAttribute

使用MessageHeaderAttribute标记的数据成员将会出现在SOAP消息的主体部分,该特性包含下面的属性:

Order:Order属性用来控制成员在SOAP主体部分中出现的位置,默认按字母顺序排列。

Name:名称。

Namespace:命名空间。

ProtectionLevel:表示保护级别。

  1. [MessageContract(IsWrapped=false,WrapperName="MyMessage",
  2. WrapperNamespace="http://oec2003.com")]
  3. public class MessageTest
  4. {
  5. [MessageBodyMember(Order = 1)]
  6. public string Email { get; set; }
  7. }
  8.  
  9. 二、如何定义契约?
  10.  
  11. 可参考资料

http://www.cnblogs.com/artech/archive/2007/02/28/659331.html

http://www.rainsts.net/article.asp?id=427

http://www.rainsts.net/article.asp?id=429

http://www.rainsts.net/article.asp?id=430

   三、契约是独立于平台的么?

WCF作为一种能够跨平台的体系框架,其应用肯定会有异构,异网的情况发生,那么作为通讯依据的契约能否自动适用于上述情况呢?答案是肯定的,契约是独立 于平台之外的,它只约束通讯的双方应该遵守什么样的规则,而丝毫不管双方各自采用的是什么样的技术和什么样的操作系统,也只有这样,WCF才能有真正的生 命力。

四、契约和以往哪种技术比较相像,又有什么不同?

如果非要拿契约和以往的技术相比较 的话,契约和asp.net xml web service的声明性编程模型甚是相似,比如在web service中在类上标记WebServiceAttribute便可以将此类用于远程调用,而将方法添加WebMethondAttribute也可 以将其暴露给远程客户端,这和WCF中的ServiceContract和OperationContract简直如出一辙,但不同的是,WCF中的契约 要比Xml Web Service中的要详尽的多,比如ServiceContract和OperationContract可以直接使用在接口上面,而实现该接口的类就继 承了这种契约声明,自动拥有契约所规范的动作和行为,这就使得程序员更方便的使用面向接口的编程方式,可以使同一服务拥有不同的实现,在新旧版本升级的同 时,能够使新老版本共同运行。

WCF入门到精通(二)——契约的更多相关文章

  1. WCF入门教程(二)如何创建WCF服务

    WCF入门教程(二)从零做起-创建WCF服务 通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK默认创建的样本 1.创建WCF服务库 2.看其生成结构 1)IService1.cs(协议) ...

  2. iOS开发-UI 从入门到精通(二)

    iOS开发-UI 从入门到精通(二)是对 iOS开发-UI 从入门到精通(一)知识点的巩固,主要以习题练习为主,增强实战经验,为以后做开发打下坚实的基础! ※开发环境和注意事项: 1.前期iOS-UI ...

  3. Python基本语法,python入门到精通[二]

    在上一篇博客Windows搭建python开发环境,python入门到精通[一]我们已经在自己的windows电脑上搭建好了python的开发环境,这篇博客呢我就开始学习一下Python的基本语法.现 ...

  4. WCF入门教程(二)从零做起

    通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK默认创建的样本 1.创建WCF服务库 2.看其生成结构 1)IService1.cs(协议) 定义了协议,具体什么操作,操作的参数和返回值 ...

  5. PHP从入门到精通(二)

     PHP从入门到精通 之PHP中的函数 各位开发者朋友大家好,自上次更新PHP的相关知识,得到了大家的广泛支持.PHP的火爆程度不言而喻,函数作为PHP中极为重要的部分,应诸位的支持,博主继续跟进更新 ...

  6. WCF入门教程(二)从零做起-创建WCF服务

    通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK默认创建的样本 1.创建WCF服务库 2.看其生成结构 1)IService1.cs(协议) 定义了协议,具体什么操作,操作的参数和返回值 ...

  7. MyBatis从入门到精通(二):MyBatis XML方式的基本用法之Select

    最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 1. 明确需求 书中提到的需求是一个基 ...

  8. WCF入门教程系列二

    一.概述 WCF能够建立一个跨平台的安全.可信赖.事务性的解决方案,是一个WebService,.Net Remoting,Enterprise Service,WSE,MSMQ的并集,有一副很经典的 ...

  9. WCF入门(十二)---WCF异常处理

    WCF服务开发者可能会遇到需要以适当的方式向客户端报告一些不可预见的错误.这样的错误,称为异常,通常是通过使用try/catch块来处理,但同样,这是非常具体的技术. 由于客户端的关注领域不是关于如何 ...

随机推荐

  1. numpy+scipy+matlotlib+scikit-learn的安装及问题解决

    NumPy(Numeric Python)系统是Python的一种开源的数值计算扩展,一个用python实现的科学计算包.它提供了许多高级的数值编程工具,如:矩阵数据类型.矢量处理,以及精密的运算库. ...

  2. VirtualBox 安装虚拟机时出现错误 VT-x features locked or unavailable in MSR.

    修改安装好的虚拟机的cup的个数重新启动的时候报了上述错误. 参考博文:http://blog.csdn.net/zklth/article/details/7019990 错误:VT-x featu ...

  3. informix 查看数据库空间名

    查看bhrs库的空间名  onstat -d 导出一个表 的结构 dbschema -d bhrs -t infotrans > xxx.sql 微网点 报表已经上线 cbs.sql 提交,生产 ...

  4. ASP.NET MVC Spring.NET NHibernate 整合

    请注明转载地址:http://www.cnblogs.com/arhat 在整合这三个技术之前,首先得说明一下整合的步骤,俗话说汗要一口一口吃,事要一件一件做.同理这个三个技术也是.那么在整合之前,需 ...

  5. poj 2559 Largest Rectangle in a Histogram (单调栈)

    http://poj.org/problem?id=2559 Largest Rectangle in a Histogram Time Limit: 1000MS   Memory Limit: 6 ...

  6. Oracle中的触发器

    创建触发器的语法: Create trigger 触发器的名字 after insert/update/delete/(select是没有触发器的) on 表名字 declare begin dbms ...

  7. 1012: [JSOI2008]最大数maxnumber

    单点更新,区间求最大值的题: 可以使用树状数组和线段树: #include<cstdio> #include<cstring> #include<algorithm> ...

  8. eclipse+tomcat7解决项目中文乱码的一个思路

    1. 在代码层面进行编码的修改操作,参考博文的方法一:http://www.cnblogs.com/longshiyVip/p/4873058.html 2. 如果项目使用了struts2等前端框架, ...

  9. JavaScript获取HTML DOM节点元素详解(转)

    在Web运用程序特别是Web 2.0程序开发中,经常要获取页面中某个元素,然后更新该元素的样式.内容等.如何获取要更新的元素,是首先要处理的疑问. 51CTO推荐阅读:JavaScript DOM文档 ...

  10. RUST叫系统编程语言,而GO是网络编程语言

    用GO你必须要搞清楚一点,GO不是面向CPU密集计算的,而是面向IO密集计算的!!!RUST才是面向CPU密集计算的语言,所以RUST叫系统编程语言,而GO是网络编程语言.GO跟JAVA的Spring ...