上次咱们稍稍讨论了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>