WCF( Windows Communication Foundation )基础
2013-09-09 23:53
609 查看
WCF(一) Windows Communication Foundation 概述
WCF被推出来很久了,但是对于刚刚接触WCF的人们来说,想必会有以下问题:
WCF是什么?为什么我们需要WCF?WCF能给我们带来什么?学习WCF的难易度如何?
以上这些问题的答案在网上已经很多介绍了,我在此本不必再浪费口舌,只是大概提一下。
WCF: Windows Communication Foundation.从名字可以看出,这是一项和通信密切相关的技术。我们知道软件设计到处是通信。当然我们必须学了以后,才能更好的知道它、运用它,而不能单单从它的名字揣测它的威力如何。
WCF提供给了我们一种面向服务(SOA)的程序设计的解决方案:何为面向服务?之前有使用过.NET Web Service 开发的朋友,很容易理解面向服务是咋回事。.Net Web Service也是更早的时候微软提出的一种面向服务的解决方案。面向服务是一种标准,不同的公司可以给出各自的实现框架。单纯的讲SOA,毕竟太抽象了。学习一下SOA的一种实现比如.Net Web Service 或WCF以后,相信不用任何文字定义,你也会深刻地理解SOA。所以,何为面向服务?这里不解释,等你学一段时间的WCF,你自己就有答案了,真的,呵呵。
WCF提供了统一的通信模型:以前我们写通信可以是:TCP/UDP,Socket等这些方式,在WCF中被统一了。至于如何统一?这里先不说了。所以,当你在项目中同时使用了多种通信方式时,可以考虑使用WCF了。
以前没有接触过Web Service 开发接受WCF也不是难事,相信我!
这次,我们只做一点WCF的概述,更为详细的知识到后面再慢慢展开。边学习,边交流。
1. 打开VS 2010 -->file-->new Project ,选择C#下面的WCF,选择WCF Library。如下图:
2.此时有了IService 文件和一个Service 文件。Service文件实现的IService中的两个函数:GetData函数和GetDataUsingDataContract函数。至于这两个函数是干嘛的?想必不用说大家都能看懂的。之后详细说明他们的角色。这里也不修改类名和函数名了,方面起见。
3.按F5运行程序,此时打开了一个WCF 的一个测试 窗口。如下图:先测试GetData函数
测试结果:
同样的方法测试GetDataUsingDataContract函数:结果如下图
4.上面完成了对WCF的函数功能的简单测试,能说明的是Service正确地实现了IService。接下来我们需要将这个WCF部署到一个Web Site中。
在解决方案上面右击:New -->New Web Site 如下图:
修改web site项目中的Service.svc 文件里面的 Service="WcfFirstDemoServiceLib.Service1" (其中意思就是已命名空间加类名的方式指定service的名字)
5.添加一个winForm程序 ,用它来调用WCF的函数。
6.给winForm 项目添加web 引用:
7.在Form1上面添加几个控件,然后再在Form1.cs中添加下列几行代码:
Form1.cs
8.Ctrl+F5 运行:
说明:这里只是概述WCF,所以全部在使用WCF的默认设置,也没有详细说明每一步的作用是什么。只是给出三个项目:项目1是WCF的库也是WCF功能核心。项目2是WCF的host用于向外界发布WCF提供的接口(注:接口这里指提供了哪些函数可被调用)。项目3是WCF的客户端用于调用WCF。其实,这里已经隐约体现出一点点分布式软件架构的意思了:有专门提供功能实现的模块,有专门提供对外公开接口的模块,有专门作为调用的模块。
后面详细WCF每一部分的。欢迎关注!!
Contract有人翻译为:协定,契约。
WCF中有四种contract: 分别是:1.Service Contract. 2.Data Contract. 3. Fault Contract. 4.Message Contract.
还拿上篇中的例子(其实就是有Visual Studio2010替我们默认生成的代码了)说事:
1.Service Contract共分为两个部分:定义部分和实现部分。
这里IService就是一个service contract的定义部分,指定了哪些函数(Operation)向外公开(即:可供Client调用)。被[OperationContract]修饰的函数可以被客户端(Client)调用。
[OperationContent]是Attribute。关于Attribute不太明白的,请参考:《别弄混了C#.的几个小概念Attribute,property,field》
Service1实现了IService接口,是Service Contract 的实现部分。VS自动生成的代码太简单了,不解释了。这里为了尽可能简单地说明问题。具体项目中,你可能需要连接数据库增、删、改、查数据,或对数据按n多复杂的业务规则进行数据处理以后,返回给client,等。
[ServiceContract] Attribute 可以有以下Property 的:
[OperationContract] Attribute 可以有以下Property 的:
1.1 我们修改一下Service的默认命名空间,使他更make scene(有意义).
打开上篇中的解决方案WcfFirstDemo.sln
右键WebHost项目下面的文件:Service.svc,如下图:
点击连接如图:
得到如图效果:
默认Namespace是http://tempuri.org/
微软官方建议:修改Service的Namespace,使其包含:公司域名+项目名+版本号(如:日期表示版本号)
修改项目:WcfFirstDemoServiceLib下面的IService.cs代码如下:
右键项目WcfFirstDemoServiceLib 选择重新编译,成功以后,重新用浏览器打开service.svc,得到如下图:
此时已经改变了Service默认的Namespace了,client端需要更新一下,否则运行client端是会报异常的.操作如下图:
1.2修改Service的Name.默认情况下定义service的接口部分(如本例:IService)的名字就是Service的名字.但有时需要让client看到的service的名字跟server端看到的的service名字不一样.
我们先看一下WCFClient项目下面的app.config
修改WcfFirstDemoServiceLib项目下的IService.cs文件
重新编译WcfFirstDemoServiceLib项目.更新client端对service的引用.此时你会发现client端app.config文件前后发生了变化:
此时WCFClient所生成的代理类的名字也会变化,你需要修改WCFClient
注:上面代码中DemoService 对应server端IService接口;DemoServiceClient对应server端的Service类.
当client端的app.config文件中只包含一个endpoint时,可以直接用proxy=new DemoServiceClient()传空参数,当然也可以传这个endpoint的name进去;但是当app.config包含多个endpoint时必须把endpoint的name传进去才能new出proxy对象.
2.DataContract.
WCF的Server和client之间利用特定格式的Message(消息)进行通信的。但是我们使用的高级语言:不论在Server端还是在client端,我们处理的业务数据都被封装成了对象。所以想把server端的对象传送到client(或相反方向)时,我们必须有能力把这些对象转换成特定格式的message,到另一端接收到message后再把它转回成对象。C#的基础类型(如int,string,float,bool等)可以做到这一点。因为一旦确定了Server端或client所用的编程语言,就可以确定这些基础类型的内存占用情况(例如:一个Server端定义的int变量在C#中占用多大内存空间是已知的,那么client端即便使用的是其他语言也完全可以计算出该变量的内存占用情况)。可是我们自己定义的类型可是五花八门了(比如:server端定义的Person类new出的object到底占用多大内存空间,就算Server端与client端使用同一种语言,Client端是不知道的Person类的对象的内存占用情况的。)
遇到这种请款下,我们怎么办呢?这时就轮到[DataContract]露面了。
遇到这种请款下,我们怎么办呢?这时就轮到[DataContract]露面了。
ServiceContract做的工作是指定service向client提供了哪些函数可供调用。DataContract做的工作就是指定在Server端与client端之间可以传送的数据。[DataContract]的作用就是指定当需要传送某个类(如:Person类)的对象时,将该对象转化成为XML.接受方接到XML以后,再按同样的方式还原成对象。
[DataContract]Attribute 标在class定义上面一行。[DataMember]Attribute标在Property定义上面一行,field不需要Attribute修饰。
[DataContract]Attribute 可以像[ServiceContract]一样设置Name和Namespace.
[DataMember] Attribute 可以有以下属性:
2.1修改DataContract的默认namespace ,
这样在client端看到的类(class)名,函数名与server看到的就不相同.
3.Fault Contract.
在WCF中处理异常(Exception)的方法有些特殊.我们不能单从server处理exception,需要进一步将Exception从server传送到client. 在后面我们再单独讨论WCF的Exception处理.
4. Message Contract.
Message Contract与Data Contract都是作用在传送的对象(object)上面.
不同的是:
datacontract是将object序列化化为xml. 实现object的各个property与xml 文本中各个node(节点)的对应);
messagecontract将对象组装成message(指定Message的Header,body).实现的是object各个property与消息的各个元素的对应.
具体的深层区别于联系,以及使用场景,我还不懂,希望有朋友对着块比较懂的,可以交流一下.如果后面等我弄懂了的话,我再专门写博文交流.
WCF中为何会有message pattern呢?
我们知道WCF的Server端与client端是通过xml 来进行交互的.message pattern其实就是指server端与client端交互xml的方式.
wcf提供以下三种pattern:
1.Request-reply:client端调用server端的公开的method后,client端需等server端method返回结果(即:reply响应)以后,才能做继续client端的下一步操作.(如:client调用server端的method往数据库中插入一条数据.server端插入数据成功以后,返回相应的数据库插入成功信息.很多情况下使用的是这种.
2.one-way:client端调用server端的公开的method后,client端不需等server端的method返回结果,便可继续client端下一步操作.(如:server端记录client端的日志(log)信息).标识为One-way的operation(函数)的返回值只能是void. 当client向server 发起了request后,不需要server做出回应的情况使用one-way message pattern.
3.duplicate:Request-Reply 和One-way都是先由client端发起的request(请求);duplicate则允许有server端发起request.
两种方式实现duplicate:一种是tcp(这里先不讲tcp的方式,先讲http的方式).一种是http. Http方式的话:是先由client端发起一次one-way 的request,然后client不等待server端返回结果,而是端继续往下执行.当server端有结果返回时,再有server端发起一次one-way的request.所以duplicate也叫callback. 我们知道当一个操作很费时的话,为了减少UI的无响应,有更好的用户体验,会使用callback.wcf也是:当server的执行很耗时的话,我们可以使用duplicate的message
pattern.
4.实现:
4.1:Requst-Reply:是最简单的
4.2:One-Way:(只需要在requst-reply的基础上,使operationContract 的IsOneWay=true即可)
4.3Duplicate:(有些复杂)有以下步骤:
4.3.1:在server端IService.cs文件中添加代码:
4.3.2:在web site项目下的web.config文件:使其支持wsDua
4.3.3在client端添加一个类文件命名为Callback.cs:
使其实现IDuplicateDemoCallback接口.
4.3.4修改client项目下的app.config文件:使其支持wsdualhttp
在开发过程中,使用configuration file (配置文件)具有很灵活的好处:以后有关于配置的改变,不必重新编译代码,只需打开configuration file 改一下就行了,省时省力.
WCF中configuration file的地位不可忽视.当然我们可以使用code的方式,实现WCF的服务的每个阶段. 但我们的软件产品是需要给客户在实际工作中使用的. 我们要让软件产品的后期维护尽可能的简单,省时省力.
WCF的核心是Service. 一个service有包含多个endpoint, 如下图:
打开VS2010,File-->New project. 选择WCF Service Library 模板. Solution Name 和project Name我们都用默认的. 点击OK.
此时创建了一个WCF Library project. 打开App.config 文件,你会看到以下内容:
注:
第1行,定义该xml file的版本和使用的字符集. 是关于该配置文件的基本信息,与程序配置无关,只管保持默认即可.
第2行,<configuration> node,关于程序内的配置,都必须包含在此node里面.
第5行,是关于debug配置. 如果是在开发阶段,把它设为true,这样调试起来方便.
第7--31行,是<system.serviceModel> node, 关于wcf service的核心配置都在这个node里面. 该node下面有两个子node:一个是<services>,另一个是<behaviors>. 除此以外,还可以有<bindings>等.<services>是<service>的集合;<behaviors>是<behavior>的集合;<bindings>是<binding>的集合.
多说一句: WCF程序设计需要注意两方面的模型:一是编程模型;二是通信模型. 一般我们做web开发只需要编程模型,通信就交给http了. 但是wcf允许我们使用http以外的其他通信协议.所以,我们考虑了编程还必须考虑通信模型.好在wcf给我们提供了方便之处:它屏蔽了开发人员对通信模型的处理,只需要我们通过bindings API创建通信模型即可. 所以,我们对bindings的指定,就是在处理通信模型.
第8--22行,是<services>node,该node下面有多个<service>node.
第9--21行,是<service>node,它的name指定了实现这个service的类名(全名,包括namespace).该<services>下面有一个<host>node,和多个<endpoint>node.(如上面我们提到的那张图) .
第10行,是<host>node, <host>下面有<baseAddress>.
第11-13行,<baseAddress> node, <add>增加一个该service的基址,<endpoint>里面的address就相对于这个baseAddress的. 如果有多个baseAddress的话是根据<endpoint>所指定的binding方式与baseAddress的形式匹配的.(如,<endpoint>所指定的binding方式是netTcpBinding,就会匹配以net.tcp://打头的baseAddress.)
第15行,<endpoint>node,<endpoint>除了name以外,还有最重要的三部分组成,简称:ABC. A是Address,B是Binding,C是Contract. Address可以是一个完整的URL,或是一个相对于基址的URL,如果为空,则使用基址.Binding指定通信模型比如:http,tcp,mssq等. Contract就是服务的contract(就是前面我们使用[OperationContract]修饰的那个服务接口).
第20行,是元数据的<endpoint>,用与发布一些元数据信息.
先到这吧.....
前述
为了让client可以使用service,我们必须host service到一个每时每刻都在运行的环境中(我们叫Host Application),因为它时刻等待着来自client的request(请求). Host有人翻译成"寄宿",我仍使用Host. Host application负责start和endservice, 然后监听来自client的request,解析client的request,然后调用相应的service. 最后把结果返回给client.
Host Application为每一个Service 创建一个ServiceHost对象. 当有多个Service是,就会创建多个ServiceHost对象. 当client需要使用多种protocol(通信协议),如Http和tcp,此时你不必创建多个service, 因为前面我们知道一个Service可以有多个endpoint(endpoint 包含Address,Binding,Contract). Binding指定不同的protocol,所以,我们只需创建多个endpoint,在binding中指定不同的protocol即可.
可以把service host到以下环境中:
1.IIS:我们需要创建一个Web Site,使用该Website去host wcf,然后将该website放到IIS中. 如果你使用了IIS去host wcf,那么只能使用http protocol. 当有request到来时,host application可以自动激活,并开始监听.
2.WAS:(Windows Process Activation Service)作为IIS7.0的一个新特性.我们同样需要创建一个web site .Vista,Windows 7, Windows Server2008 等操作系统可以安装WAS. 如果你使用了WAS去host wcf,可以使用http ,tcp,MSMQ,Named Pipe protocol. 当有request到来时,host application可以自动激活,并开始监听.
3.Managed Application(托管程序,如Console,WinFrom,WPF): Self-Hosting. 当有request到来时,host application不能自动激活.需要在代码中手动new出serviceHost对象.
我们如何选择哪一种host方式呢?
答案是:取决于你的操作系统,和通信需求,和特定场景.
1.如果你的操作系统是windows server2003,并且程序只用http即可满足需求. 那么使用IIS去host. 如果程序除了使用http不可满足需求(除了http,还需要tcp),则要创建window 服务去host.
2.如果你的操作系统是windows server2008(或 windows 7 )使用WAS. 因为它可以支持更多的protocol.
3.如果仅仅用于演示,可以使用Console去host. 但是release到真正的产品时,最好用winForm或WPF.
对于每一种方式,我们如何实现呢?
WCF被推出来很久了,但是对于刚刚接触WCF的人们来说,想必会有以下问题:
WCF是什么?为什么我们需要WCF?WCF能给我们带来什么?学习WCF的难易度如何?
以上这些问题的答案在网上已经很多介绍了,我在此本不必再浪费口舌,只是大概提一下。
WCF: Windows Communication Foundation.从名字可以看出,这是一项和通信密切相关的技术。我们知道软件设计到处是通信。当然我们必须学了以后,才能更好的知道它、运用它,而不能单单从它的名字揣测它的威力如何。
WCF提供给了我们一种面向服务(SOA)的程序设计的解决方案:何为面向服务?之前有使用过.NET Web Service 开发的朋友,很容易理解面向服务是咋回事。.Net Web Service也是更早的时候微软提出的一种面向服务的解决方案。面向服务是一种标准,不同的公司可以给出各自的实现框架。单纯的讲SOA,毕竟太抽象了。学习一下SOA的一种实现比如.Net Web Service 或WCF以后,相信不用任何文字定义,你也会深刻地理解SOA。所以,何为面向服务?这里不解释,等你学一段时间的WCF,你自己就有答案了,真的,呵呵。
WCF提供了统一的通信模型:以前我们写通信可以是:TCP/UDP,Socket等这些方式,在WCF中被统一了。至于如何统一?这里先不说了。所以,当你在项目中同时使用了多种通信方式时,可以考虑使用WCF了。
以前没有接触过Web Service 开发接受WCF也不是难事,相信我!
这次,我们只做一点WCF的概述,更为详细的知识到后面再慢慢展开。边学习,边交流。
1. 打开VS 2010 -->file-->new Project ,选择C#下面的WCF,选择WCF Library。如下图:
2.此时有了IService 文件和一个Service 文件。Service文件实现的IService中的两个函数:GetData函数和GetDataUsingDataContract函数。至于这两个函数是干嘛的?想必不用说大家都能看懂的。之后详细说明他们的角色。这里也不修改类名和函数名了,方面起见。
3.按F5运行程序,此时打开了一个WCF 的一个测试 窗口。如下图:先测试GetData函数
测试结果:
同样的方法测试GetDataUsingDataContract函数:结果如下图
4.上面完成了对WCF的函数功能的简单测试,能说明的是Service正确地实现了IService。接下来我们需要将这个WCF部署到一个Web Site中。
在解决方案上面右击:New -->New Web Site 如下图:
修改web site项目中的Service.svc 文件里面的 Service="WcfFirstDemoServiceLib.Service1" (其中意思就是已命名空间加类名的方式指定service的名字)
5.添加一个winForm程序 ,用它来调用WCF的函数。
6.给winForm 项目添加web 引用:
7.在Form1上面添加几个控件,然后再在Form1.cs中添加下列几行代码:
Form1.cs
8.Ctrl+F5 运行:
说明:这里只是概述WCF,所以全部在使用WCF的默认设置,也没有详细说明每一步的作用是什么。只是给出三个项目:项目1是WCF的库也是WCF功能核心。项目2是WCF的host用于向外界发布WCF提供的接口(注:接口这里指提供了哪些函数可被调用)。项目3是WCF的客户端用于调用WCF。其实,这里已经隐约体现出一点点分布式软件架构的意思了:有专门提供功能实现的模块,有专门提供对外公开接口的模块,有专门作为调用的模块。
后面详细WCF每一部分的。欢迎关注!!
WCF(二) Contract
上篇只是介绍了WCF的概述。具体的设置全是使用默认,这当然不可能满足我们开发的需要。如果仔细理一理的话,你会发现WCF里面的设置其实不算多的(与SharePoint比较的话)。从这篇开始,我们一点一点来展开学习。这次先提最最常用的Contract。Contract有人翻译为:协定,契约。
WCF中有四种contract: 分别是:1.Service Contract. 2.Data Contract. 3. Fault Contract. 4.Message Contract.
还拿上篇中的例子(其实就是有Visual Studio2010替我们默认生成的代码了)说事:
1.Service Contract共分为两个部分:定义部分和实现部分。
1 [ServiceContract] 2 public interface IService1 3 { 4 [OperationContract] 5 string GetData(int value); 6 7 [OperationContract] 8 CompositeType GetDataUsingDataContract(CompositeType composite); 9 10 }
这里IService就是一个service contract的定义部分,指定了哪些函数(Operation)向外公开(即:可供Client调用)。被[OperationContract]修饰的函数可以被客户端(Client)调用。
[OperationContent]是Attribute。关于Attribute不太明白的,请参考:《别弄混了C#.的几个小概念Attribute,property,field》
1 public class Service1 : IService1 2 { 3 public string GetData(int value) 4 { 5 return string.Format("You entered: {0}", value); 6 } 7 8 public CompositeType GetDataUsingDataContract(CompositeType composite) 9 { 10 if (composite == null) 11 { 12 throw new ArgumentNullException("composite"); 13 } 14 if (composite.BoolValue) 15 { 16 composite.StringValue += "Suffix"; 17 } 18 return composite; 19 } 20 }
Service1实现了IService接口,是Service Contract 的实现部分。VS自动生成的代码太简单了,不解释了。这里为了尽可能简单地说明问题。具体项目中,你可能需要连接数据库增、删、改、查数据,或对数据按n多复杂的业务规则进行数据处理以后,返回给client,等。
[ServiceContract] Attribute 可以有以下Property 的:
CallbackContract | 设置callback的类型:Duplicate指Service Host和Client之间进行双向通信 |
ConfigurationName | 指定配置文件中某个configuration的名字 |
HasProtectionLevel | 标示是否可以处理安全消息 |
Name | 给contract指定一个名字,在client端可见的名字,默认就是接口名字 |
Namespace | 给消息指定一个命名空间 |
ProtectionLevel | |
SessionMode | 指允许,还是不允许,还是强制session |
Action | 对请求设置WS-Addressing 的action |
AsynchPattern | 异步模式 |
HasProtectionLevel | 消息是否加密,签名 |
IsInitiating | 表明该函数被调用开始时是否要在server上面初始化一个session |
IsOneWay | 表明函数被client调用以后,client是否会等待函数返回 |
IsTerminating | 表明该函数被调用结束时是否要在server上面关闭session |
Name | 设置函数的名字,在client端可见的名字,默认就是函数名字 |
ProtectionLevel | |
ReplyAction | 设置函数返回消息的SOAP action |
打开上篇中的解决方案WcfFirstDemo.sln
右键WebHost项目下面的文件:Service.svc,如下图:
点击连接如图:
得到如图效果:
默认Namespace是http://tempuri.org/
微软官方建议:修改Service的Namespace,使其包含:公司域名+项目名+版本号(如:日期表示版本号)
修改项目:WcfFirstDemoServiceLib下面的IService.cs代码如下:
1 [ServiceContract(Namespace="http://wwww.cnblogs.com/WCF/2012/07/28")] 2 public interface IService1 3 { 4 [OperationContract] 5 string GetData(int value); 6 7 [OperationContract] 8 CompositeType GetDataUsingDataContract(CompositeType composite); 9 10 }
右键项目WcfFirstDemoServiceLib 选择重新编译,成功以后,重新用浏览器打开service.svc,得到如下图:
此时已经改变了Service默认的Namespace了,client端需要更新一下,否则运行client端是会报异常的.操作如下图:
1.2修改Service的Name.默认情况下定义service的接口部分(如本例:IService)的名字就是Service的名字.但有时需要让client看到的service的名字跟server端看到的的service名字不一样.
我们先看一下WCFClient项目下面的app.config
修改WcfFirstDemoServiceLib项目下的IService.cs文件
1 [ServiceContract(Namespace="http://wwww.cnblogs.com/WCF/2012/07/28",Name="DemoService")] 2 public interface IService1 3 { 4 [OperationContract(Name="GetAge")] 5 string GetData(int value); 6 7 [OperationContract] 8 CompositeType GetDataUsingDataContract(CompositeType composite); 9 10 }
重新编译WcfFirstDemoServiceLib项目.更新client端对service的引用.此时你会发现client端app.config文件前后发生了变化:
此时WCFClient所生成的代理类的名字也会变化,你需要修改WCFClient
1 DemoService proxy = null;
1 private void Form1_Load(object sender, EventArgs e) 2 { 3 proxy = new DemoServiceClient("BasicHttpBinding_DemoService"); 4 5 }
1 private void btnGetData_Click(object sender, EventArgs e) 2 { 3 this.tbOutputBox.Text = proxy.GetAge(Convert.ToInt32(this.tbInputbox.Text)); 4 }
注:上面代码中DemoService 对应server端IService接口;DemoServiceClient对应server端的Service类.
当client端的app.config文件中只包含一个endpoint时,可以直接用proxy=new DemoServiceClient()传空参数,当然也可以传这个endpoint的name进去;但是当app.config包含多个endpoint时必须把endpoint的name传进去才能new出proxy对象.
2.DataContract.
WCF的Server和client之间利用特定格式的Message(消息)进行通信的。但是我们使用的高级语言:不论在Server端还是在client端,我们处理的业务数据都被封装成了对象。所以想把server端的对象传送到client(或相反方向)时,我们必须有能力把这些对象转换成特定格式的message,到另一端接收到message后再把它转回成对象。C#的基础类型(如int,string,float,bool等)可以做到这一点。因为一旦确定了Server端或client所用的编程语言,就可以确定这些基础类型的内存占用情况(例如:一个Server端定义的int变量在C#中占用多大内存空间是已知的,那么client端即便使用的是其他语言也完全可以计算出该变量的内存占用情况)。可是我们自己定义的类型可是五花八门了(比如:server端定义的Person类new出的object到底占用多大内存空间,就算Server端与client端使用同一种语言,Client端是不知道的Person类的对象的内存占用情况的。)
遇到这种请款下,我们怎么办呢?这时就轮到[DataContract]露面了。
遇到这种请款下,我们怎么办呢?这时就轮到[DataContract]露面了。
ServiceContract做的工作是指定service向client提供了哪些函数可供调用。DataContract做的工作就是指定在Server端与client端之间可以传送的数据。[DataContract]的作用就是指定当需要传送某个类(如:Person类)的对象时,将该对象转化成为XML.接受方接到XML以后,再按同样的方式还原成对象。
[DataContract]Attribute 标在class定义上面一行。[DataMember]Attribute标在Property定义上面一行,field不需要Attribute修饰。
1 [DataContract] 2 public class CompositeType 3 { 4 bool boolValue = true; 5 string stringValue = "Hello "; 6 7 [DataMember] 8 public bool BoolValue 9 { 10 get { return boolValue; } 11 set { boolValue = value; } 12 } 13 14 [DataMember] 15 public string StringValue 16 { 17 get { return stringValue; } 18 set { stringValue = value; } 19 } 20 }
[DataContract]Attribute 可以像[ServiceContract]一样设置Name和Namespace.
[DataMember] Attribute 可以有以下属性:
EmitDefaultValue | 设置一个默认值 |
IsRequired | 进行序列化/反序列化时该值一定不可为空值 |
Name | Property的名字 |
Order | 设置进行序列化/反序列化的顺序 |
1 [DataContract(Namespace = "http://wwww.cnblogs.com/WCF/2012/07/28", Name = "CompositeTypeDemo")] 2 public class CompositeType 3 { 4 bool boolValue = true; 5 string stringValue = "Hello "; 6 7 [DataMember(Name="GetBool")] 8 public bool BoolValue 9 { 10 get { return boolValue; } 11 set { boolValue = value; } 12 } 13 14 [DataMember(Name="GetString")] 15 public string StringValue 16 { 17 get { return stringValue; } 18 set { stringValue = value; } 19 } 20 }
这样在client端看到的类(class)名,函数名与server看到的就不相同.
3.Fault Contract.
在WCF中处理异常(Exception)的方法有些特殊.我们不能单从server处理exception,需要进一步将Exception从server传送到client. 在后面我们再单独讨论WCF的Exception处理.
4. Message Contract.
Message Contract与Data Contract都是作用在传送的对象(object)上面.
不同的是:
datacontract是将object序列化化为xml. 实现object的各个property与xml 文本中各个node(节点)的对应);
messagecontract将对象组装成message(指定Message的Header,body).实现的是object各个property与消息的各个元素的对应.
具体的深层区别于联系,以及使用场景,我还不懂,希望有朋友对着块比较懂的,可以交流一下.如果后面等我弄懂了的话,我再专门写博文交流.
WCF(三) Message pattern
上次咱们稍稍讨论了WCF中的contract,这次咱们讨论Message Pattern.WCF中为何会有message pattern呢?
我们知道WCF的Server端与client端是通过xml 来进行交互的.message pattern其实就是指server端与client端交互xml的方式.
wcf提供以下三种pattern:
1.Request-reply:client端调用server端的公开的method后,client端需等server端method返回结果(即:reply响应)以后,才能做继续client端的下一步操作.(如:client调用server端的method往数据库中插入一条数据.server端插入数据成功以后,返回相应的数据库插入成功信息.很多情况下使用的是这种.
2.one-way:client端调用server端的公开的method后,client端不需等server端的method返回结果,便可继续client端下一步操作.(如:server端记录client端的日志(log)信息).标识为One-way的operation(函数)的返回值只能是void. 当client向server 发起了request后,不需要server做出回应的情况使用one-way message pattern.
3.duplicate:Request-Reply 和One-way都是先由client端发起的request(请求);duplicate则允许有server端发起request.
两种方式实现duplicate:一种是tcp(这里先不讲tcp的方式,先讲http的方式).一种是http. Http方式的话:是先由client端发起一次one-way 的request,然后client不等待server端返回结果,而是端继续往下执行.当server端有结果返回时,再有server端发起一次one-way的request.所以duplicate也叫callback. 我们知道当一个操作很费时的话,为了减少UI的无响应,有更好的用户体验,会使用callback.wcf也是:当server的执行很耗时的话,我们可以使用duplicate的message
pattern.
4.实现:
4.1:Requst-Reply:是最简单的
1 [ServiceContract(CallbackContract = typeof(IDuplicateDemoCallback))] 2 public interface IService1 3 { 4 // 在函数中,我们让线程暂停,模拟耗时的操作. 5 // 参数:interval为暂停的毫秒数,由调用该method的client端设定. 6 [OperationContract] 7 void RequestReply(int interval); 8 9 [OperationContract] 10 void DuplicateCommunicate(int interval); 11 12 }
4.2:One-Way:(只需要在requst-reply的基础上,使operationContract 的IsOneWay=true即可)
1 [ServiceContract(CallbackContract = typeof(IDuplicateDemoCallback))] 2 public interface IService1 3 { 4 // 在函数中,我们让线程暂停,模拟耗时的操作. 5 // 参数:interval为暂停的毫秒数,由调用该method的client端设定. 6 [OperationContract(IsOneWay = true)] 7 void RequestReply(int interval); 8 9 [OperationContract(IsOneWay = true)] 10 void DuplicateCommunicate(int interval); 11 12 }
4.3Duplicate:(有些复杂)有以下步骤:
4.3.1:在server端IService.cs文件中添加代码:
1 // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together. 2 [ServiceContract(CallbackContract = typeof(IDuplicateDemoCallback))] 3 public interface IService1 4 { 5 // 在函数中,我们让线程暂停,模拟耗时的操作. 6 // 参数:interval为暂停的毫秒数,由调用该method的client端设定. 7 [OperationContract(IsOneWay=true)] 8 void RequestReply(int interval); 9 10 [OperationContract(IsOneWay=true)] 11 void DuplicateCommunicate(int interval); 12 13 14 } 15 16 public interface IDuplicateDemoCallback 17 { 18 [OperationContract(IsOneWay=true)] 19 void DuplicateCommunicateCallback(string callbackMessage); 20 }
4.3.2:在web site项目下的web.config文件:使其支持wsDua
1 <?xml version="1.0"?> 2 <configuration> 3 4 <system.web> 5 <compilation debug="false" targetFramework="4.0" /> 6 </system.web> 7 <system.serviceModel> 8 <behaviors> 9 <serviceBehaviors> 10 <behavior> 11 <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --> 12 <serviceMetadata httpGetEnabled="true"/> 13 <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> 14 <serviceDebug includeExceptionDetailInFaults="false"/> 15 </behavior> 16 </serviceBehaviors> 17 </behaviors> 18 <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> 19 20 <services> 21 <service name="WcfMessagePatternLib.Service1" behaviorConfiguration=""> 22 <!-- Service Endpoints --> 23 <endpoint address="" binding="wsDualHttpBinding" contract="WcfMessagePatternLib.IService1"> 24 <identity> 25 <dns value="localhost"/> 26 </identity> 27 </endpoint> 28 <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 29 </service> 30 </services> 31 32 33 </system.serviceModel> 34 <system.webServer> 35 <modules runAllManagedModulesForAllRequests="true"/> 36 </system.webServer> 37 38 </configuration>
4.3.3在client端添加一个类文件命名为Callback.cs:
使其实现IDuplicateDemoCallback接口.
1 class Callback:ServiceReference1.IService1Callback 2 { 3 public void DuplicateCommunicateCallback(string callbackMessage) 4 { 5 MessageBox.Show(callbackMessage); 6 } 7 }
1 private void Form1_Load(object sender, EventArgs e) 2 { 3 var context = new InstanceContext(new Callback()); 4 proxy = new Service1Client(context); 5 }
4.3.4修改client项目下的app.config文件:使其支持wsdualhttp
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <system.serviceModel> 4 <bindings> 5 <wsDualHttpBinding> 6 <binding name="WSDualHttpBinding_IService1" closeTimeout="00:01:00" 7 openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" 8 bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" 9 maxBufferPoolSize="524288" maxReceivedMessageSize="65536" 10 messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"> 11 <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 12 maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 13 <reliableSession ordered="true" inactivityTimeout="00:10:00" /> 14 <security mode="Message"> 15 <message clientCredentialType="Windows" negotiateServiceCredential="true" 16 algorithmSuite="Default" /> 17 </security> 18 </binding> 19 </wsDualHttpBinding> 20 </bindings> 21 <client> 22 <endpoint address="http://localhost:8167/WebHost/Service.svc" 23 binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IService1" 24 contract="ServiceReference1.IService1" name="WSDualHttpBinding_IService1"> 25 <identity> 26 <dns value="localhost" /> 27 </identity> 28 </endpoint> 29 </client> 30 </system.serviceModel> 31 </configuration>
WCF(四) Configuration file (配置文件)
前面大致介绍了点wcf的几个小小的基本概念. 任何一个新技术,都能给我们带来一大堆的基本概念. 当然WCF也不例外. 关于WCF更多的概念,在以后再讨论.我们先讨论如何在不深入了解这一大堆学术定义的前提下,使用这项技术.在开发过程中,使用configuration file (配置文件)具有很灵活的好处:以后有关于配置的改变,不必重新编译代码,只需打开configuration file 改一下就行了,省时省力.
WCF中configuration file的地位不可忽视.当然我们可以使用code的方式,实现WCF的服务的每个阶段. 但我们的软件产品是需要给客户在实际工作中使用的. 我们要让软件产品的后期维护尽可能的简单,省时省力.
WCF的核心是Service. 一个service有包含多个endpoint, 如下图:
打开VS2010,File-->New project. 选择WCF Service Library 模板. Solution Name 和project Name我们都用默认的. 点击OK.
此时创建了一个WCF Library project. 打开App.config 文件,你会看到以下内容:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 4 <system.web> 5 <compilation debug="true" /> 6 </system.web> 7 <system.serviceModel> 8 <services> 9 <service name="WcfServiceLibrary4.Service1"> 10 <host> 11 <baseAddresses> 12 <add baseAddress = "http://localhost:8732/Design_Time_Addresses/WcfServiceLibrary4/Service1/" /> 13 </baseAddresses> 14 </host> 15 <endpoint address ="" binding="wsHttpBinding" contract="WcfServiceLibrary4.IService1"> 16 <identity> 17 <dns value="localhost"/> 18 </identity> 19 </endpoint> 20 <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 21 </service> 22 </services> 23 <behaviors> 24 <serviceBehaviors> 25 <behavior> 26 <serviceMetadata httpGetEnabled="True"/> 27 <serviceDebug includeExceptionDetailInFaults="False" /> 28 </behavior> 29 </serviceBehaviors> 30 </behaviors> 31 </system.serviceModel> 32 33 </configuration>
注:
第1行,定义该xml file的版本和使用的字符集. 是关于该配置文件的基本信息,与程序配置无关,只管保持默认即可.
第2行,<configuration> node,关于程序内的配置,都必须包含在此node里面.
第5行,是关于debug配置. 如果是在开发阶段,把它设为true,这样调试起来方便.
第7--31行,是<system.serviceModel> node, 关于wcf service的核心配置都在这个node里面. 该node下面有两个子node:一个是<services>,另一个是<behaviors>. 除此以外,还可以有<bindings>等.<services>是<service>的集合;<behaviors>是<behavior>的集合;<bindings>是<binding>的集合.
多说一句: WCF程序设计需要注意两方面的模型:一是编程模型;二是通信模型. 一般我们做web开发只需要编程模型,通信就交给http了. 但是wcf允许我们使用http以外的其他通信协议.所以,我们考虑了编程还必须考虑通信模型.好在wcf给我们提供了方便之处:它屏蔽了开发人员对通信模型的处理,只需要我们通过bindings API创建通信模型即可. 所以,我们对bindings的指定,就是在处理通信模型.
第8--22行,是<services>node,该node下面有多个<service>node.
第9--21行,是<service>node,它的name指定了实现这个service的类名(全名,包括namespace).该<services>下面有一个<host>node,和多个<endpoint>node.(如上面我们提到的那张图) .
第10行,是<host>node, <host>下面有<baseAddress>.
第11-13行,<baseAddress> node, <add>增加一个该service的基址,<endpoint>里面的address就相对于这个baseAddress的. 如果有多个baseAddress的话是根据<endpoint>所指定的binding方式与baseAddress的形式匹配的.(如,<endpoint>所指定的binding方式是netTcpBinding,就会匹配以net.tcp://打头的baseAddress.)
第15行,<endpoint>node,<endpoint>除了name以外,还有最重要的三部分组成,简称:ABC. A是Address,B是Binding,C是Contract. Address可以是一个完整的URL,或是一个相对于基址的URL,如果为空,则使用基址.Binding指定通信模型比如:http,tcp,mssq等. Contract就是服务的contract(就是前面我们使用[OperationContract]修饰的那个服务接口).
第20行,是元数据的<endpoint>,用与发布一些元数据信息.
先到这吧.....
WCF(五) Host WCF Service
这次我们讨论Host a WCF service.前述
为了让client可以使用service,我们必须host service到一个每时每刻都在运行的环境中(我们叫Host Application),因为它时刻等待着来自client的request(请求). Host有人翻译成"寄宿",我仍使用Host. Host application负责start和endservice, 然后监听来自client的request,解析client的request,然后调用相应的service. 最后把结果返回给client.
Host Application为每一个Service 创建一个ServiceHost对象. 当有多个Service是,就会创建多个ServiceHost对象. 当client需要使用多种protocol(通信协议),如Http和tcp,此时你不必创建多个service, 因为前面我们知道一个Service可以有多个endpoint(endpoint 包含Address,Binding,Contract). Binding指定不同的protocol,所以,我们只需创建多个endpoint,在binding中指定不同的protocol即可.
可以把service host到以下环境中:
1.IIS:我们需要创建一个Web Site,使用该Website去host wcf,然后将该website放到IIS中. 如果你使用了IIS去host wcf,那么只能使用http protocol. 当有request到来时,host application可以自动激活,并开始监听.
2.WAS:(Windows Process Activation Service)作为IIS7.0的一个新特性.我们同样需要创建一个web site .Vista,Windows 7, Windows Server2008 等操作系统可以安装WAS. 如果你使用了WAS去host wcf,可以使用http ,tcp,MSMQ,Named Pipe protocol. 当有request到来时,host application可以自动激活,并开始监听.
3.Managed Application(托管程序,如Console,WinFrom,WPF): Self-Hosting. 当有request到来时,host application不能自动激活.需要在代码中手动new出serviceHost对象.
我们如何选择哪一种host方式呢?
答案是:取决于你的操作系统,和通信需求,和特定场景.
1.如果你的操作系统是windows server2003,并且程序只用http即可满足需求. 那么使用IIS去host. 如果程序除了使用http不可满足需求(除了http,还需要tcp),则要创建window 服务去host.
2.如果你的操作系统是windows server2008(或 windows 7 )使用WAS. 因为它可以支持更多的protocol.
3.如果仅仅用于演示,可以使用Console去host. 但是release到真正的产品时,最好用winForm或WPF.
对于每一种方式,我们如何实现呢?
相关文章推荐
- Essential Windows Communication Foundation (WCF): For .NET Framework 3.5
- 第一节 什么是WCF(Windows Communication Foundation)?WCF的相关介绍
- .NET Framework 4.6 and 4.5 > 开发指南 > 使用 WCF 的面向服务的应用程序 > Windows Communication Foundation (WCF)
- WCF入门教程 Windows Communication Foundation
- Windows Communication Foundation(WCF)
- 第二节 Windows Communication Foundation 基础概念
- WCF (Windows Communication Foundation) Overview
- Windows Communication Foundation (WCF) Firestarter Note
- Windows Communication Foundation 基础概念
- (翻译)Windows Communication Foundation (Workshop)-Part 2:在WCF中操作会话
- Windows Communication Foundation (WCF) 通道堆栈编码
- Windows Communication Foundation(WCF) 一步一步从入门到精通
- WCF (Windows Communication Foundation) Create & Implement a WCF Host
- Windows Communication Foundation(WCF)
- [WCF] Windows Communication Foundation
- WCF(一) Windows Communication Foundation 概述
- Windows Communication Foundation (WCF) Best Practices
- Windows 通信基础(Windows Communication Foundation)
- Windows Communication Foundation and RESTful Web Services Primer(教你制作rest wcf)
- Windows Communication Foundation (WCF) 概念概述