六 WCF4.0中的简化配置功能

WCF4.0为了简化服务配置,提供了默认的终结点、绑定和服务行为。也就是说,在开发WCF服务程序的时候,即使我们不提供显示的 服务终结点,WCF框架也能为我们的服务提供一些默认配置功能的服务终结点。当然也包含默认的绑定和默认的服务行为。这一切都是为了简化配置过程,避免一 些不必要的错误。

下面我们就来通过代码示例来体验一下WCF4.0提供简化配置的功能。

(1)默认终结点

  默认终结点(Default Endpoints)指的是,如果开发人员没有为服务显示配置服务终结点(Endpoints)。WCF4.0会根据已有的基地址,产生针对每个基地址一个默认的终结点。

  我们在前面的示例之中,都是以标准的WCF服务配置进行配置文件的书写,明确提供了Address、Binding和Contract,也就是ABC,完整代码见之前的示例。终结点配置代码如下:

  1. <service name="WCFService.WCFService">
  2. <endpoint name="endpointService"
  3. address="http://localhost:8000/WCFService"
  4. binding="wsHttpBinding"
  5. contract="WCFService.IWCFService">
  6. </endpoint>
  7. </service>

启动之后生成的地址如下图。

  现在我们在配置文件中的<host>节点中的<baseAddress>节点添加基地址,那么在<service>节点中的<address>可以使用相对地址。不过这个配置写法只能在WCF4.0之后的版本中使用,只要你提供了一个服务的基地址,即使没有服务终结点配置,WCF框架会自动根据基地址创建一个默认的终结点,也就是Default Endpoint。请看下面的服务配置信息:

  1. <service name="WCFService.WCFService">
  2. <host>
  3. <baseAddresses>
  4. <add baseAddress="http://localhost:8000/"/>
  5. <add baseAddress="http://localhost:8080/"/>
  6. </baseAddresses>
  7. </host>
  8. </service>

不过这样配置,程序运行时会报错,错误信息如下:

其他信息: 此集合已经采用方案 http 的地址。此集合中每个方案中最多只能包含一个地址。如果服务承载于 IIS 中,则可以通过将“system.serviceModel/serviceHostingEnvironment/multipleSiteBindingsEnabled”设置为 true,或指定“system.serviceModel/serviceHostingEnvironment/baseAddressPrefixFilters”来解决此问题。

正确的配置方式如下:

  1. <service name="WCFService.WCFService">
  2. <host>
  3. <baseAddresses>
  4. <add baseAddress="http://localhost:8000/"/>
  5. <add baseAddress="net.tcp://localhost:8080/"/>
  6. </baseAddresses>
  7. </host>
  8. </service>

一般WCF4.0里我们只指定一个baseAddress,做为示例,我在这里指定了2个服务的baseAddress。那么按照理论,WCF框架会为我们产生2个默认的终结点。运行代码结果如下图:

  这里我们能看到根据已有的两个baseAddress,WCF框架产生了2个默认服务终结点。如果我们把2个基地址也去除,运行WCF Host程序,就会出现没有终结点的错误。这里针对每个不同的基地址,WCF4.0提供了不同的默认绑定。如上图中的,第一个终结点是使用Http协议,WCF 4.0框架提供的是 basicHttpBinding。第二个终点使用的是net.tcp协议,WCF 4.0框架提供的是netTcpBinding。

(2)指定终结点

如果我们显示指定服务的终结点,那么WCF就不会基于baseAddress产生新的默认的终结点。修改配置代码如下:

  1. <services>
  2. <service name="WCFService.WCFService" >
  3. <endpoint name="endpointService"
  4. address="http://localhost:8100/WCFService"
  5. binding="basicHttpBinding"
  6. contract="WCFService.IWCFService">
  7. </endpoint>
  8. <!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />-->
  9. <host>
  10. <baseAddresses>
  11. <add baseAddress="http://localhost:8000/"/>
  12. <add baseAddress="net.tcp://localhost:8080/"/>
  13. </baseAddresses>
  14.  
  15. </host>
  16.  
  17. </service>
  18.  
  19. </services>

  这时在运行WCF Host程序,就不会产生新的默认的终结点。运行结果如下图:

(3)强制为每个基地址添加默认终结点

  如果我们想为每个基地址baseAddress, 保留产生的默认的服务终结点,还想添加自己的服务终结点怎么办呢?因为之前WCF服务提供了显示的终结点以后,默认服务终结点就消失了。这个时候我们可以 通过调用Host的AddDefaultEndpoints()方法实现这一目的。此方法的目的会为服务里每个基地址产生一个终结点。绑定也是使用默认的 配置。代码就是:host.AddDefaultEndpoints();新的运行结果如下,这里理论上,我们会得到3个服务终结点:2个默认+1个显示 配置。运行程序结果如下图:

(4) 绑定协议映射:

  默认协议映射(Default Protocol Mapping)。WCF提供针对绑定协议的映射机制,用来简化配置。我们可以在服务配置里指定某个地址结构映射到特定的绑定上,WCF会自动在服务里更新匹配该地址结构的默认终结点的绑定为映射的绑定。

这里把这个概念放到此处,根据上面的例子来解释,很简单。要使用绑定映射功能。我需要在服务里指定使用的映射。配置文件里的 <protocolMapping>节点,我们可以在其内部指定此解决方案里使用的服务的绑定映射。配置代码如下:

  1. <system.serviceModel>
  2. <protocolMapping>
  3. <add scheme="http" binding="basicHttpBinding"/>
  4. <add scheme="net.tcp" binding="netTcpBinding"/>
  5. <add scheme="net.pipe" binding="netNamedPipeBinding"/>
  6. <add scheme="net.msmq" binding="netMsmqBinding"/>
  7. </protocolMapping>

修改后的配置代码如下:

  1. <system.serviceModel>
  2. <protocolMapping>
  3. <add scheme="http" binding="webHttpBinding"/>
  4. <add scheme="net.tcp" binding="netTcpBinding"/>
  5. <add scheme="net.pipe" binding="netNamedPipeBinding"/>
  6. <add scheme="net.msmq" binding="netMsmqBinding"/>
  7. </protocolMapping>
  8. </system.serviceModel>

  注意上图运行结果,基于http基地址产生的默认终结点,使用的绑定是basicHttpBinding。我们这里为了测试,把http的映射修改为webHttpBinding,然后启动Host程序,再来观察一下结果。运行结果如下图:

   观察上图中的第二个终结点,绑定已经变为webHttpBinding。

配置文件:

  1. <?xml version="1.0"?>
  2. <configuration>
  3. <system.web>
  4. <compilation debug="true"/>
  5. </system.web>
  6. <!-- When deploying the service library project, the content of the config file must be added to the host's
  7.  
  8. app.config file. System.Configuration does not support config files for libraries. -->
  9.  
  10. <system.serviceModel>
  11.  
  12. <protocolMapping>
  13. <add scheme="http" binding="basicHttpBinding"/>
  14. <add scheme="net.tcp" binding="netTcpBinding"/>
  15. <add scheme="net.pipe" binding="netNamedPipeBinding"/>
  16. <add scheme="net.msmq" binding="netMsmqBinding"/>
  17. </protocolMapping>
  18. <services>
  19. <service name="WCFService.WCFService" >
  20. <endpoint name="endpointService"
  21. address="http://localhost:8100/WCFService"
  22. binding="basicHttpBinding"
  23. contract="WCFService.IWCFService">
  24. </endpoint>
  25. <!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />-->
  26. <host>
  27. <baseAddresses>
  28. <add baseAddress="http://localhost:8000/"/>
  29. <add baseAddress="net.tcp://localhost:8080/"/>
  30. </baseAddresses>
  31. </host>
  32. </service>
  33. </services>
  34. <behaviors>
  35. <serviceBehaviors >
  36. <behavior >
  37. <serviceMetadata httpGetEnabled="true" />
  38. <serviceDebug includeExceptionDetailInFaults="false"/>
  39. </behavior>
  40. </serviceBehaviors>
  41. </behaviors>
  42. <bindings>
  43. <basicHttpBinding></basicHttpBinding>
  44. <basicHttpContextBinding></basicHttpContextBinding>
  45. <netMsmqBinding></netMsmqBinding>
  46. <netNamedPipeBinding></netNamedPipeBinding>
  47. <webHttpBinding></webHttpBinding>
  48. <wsHttpBinding>
  49. <binding >
  50. <security mode="Message">
  51. <transport clientCredentialType="None">
  52. </transport>
  53. <message clientCredentialType="Certificate"/>
  54. </security>
  55. </binding>
  56. </wsHttpBinding>
  57. <wsDualHttpBinding></wsDualHttpBinding>
  58. </bindings>
  59. </system.serviceModel>
  60. <startup>
  61. <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  62. </startup>
  63. </configuration>

代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.ServiceModel;
  6. using System.ServiceModel.Description;
  7. using System.Runtime.Serialization;
  8. namespace WCFHost
  9. {
  10.  
  11. //采用自托管方式,也可以是IIS、WAS,Windows服务等用户自定义程序托管服务
  12. //Simple Configration
  13. public class WCFHost
  14. {
  15. static void Main(string[] args)
  16. {
  17.  
  18. //反射方式创建服务实例,
  19. ServiceHost host = new ServiceHost(typeof(WCFService.WCFService));//,
  20.  
  21. //为WCF服务中的每个基地址生成一个终结点
  22. host.AddDefaultEndpoints();
  23. //判断是否以及打开连接,如果尚未打开,就打开侦听端口
  24. if (host.State !=CommunicationState.Opening)
  25. host.Open();
  26. //显示运行状态
  27. Console.ForegroundColor = ConsoleColor.Red;
  28. Console.WriteLine("WCF 服务寄宿程序开始运行! WCF 服务状态 {0}",host.State);
  29.  
  30. //print endpoint information
  31. Console.WriteLine("Endpoints count is {0}", host.Description.Endpoints.Count);
  32. Console.ForegroundColor = ConsoleColor.Yellow;
  33. foreach (ServiceEndpoint se in host.Description.Endpoints)
  34. {
  35. Console.WriteLine("[终结点]: {0}\r\n\t[A-地址]: {1} \r\n\t [B-绑定]: {2} \r\n\t [C-协定]: {3}",
  36. se.Name,se.Address, se.Binding.Name, se.Contract.Name);
  37.  
  38. }
  39.  
  40. //等待输入即停止服务
  41. Console.ForegroundColor = ConsoleColor.Red;
  42. Console.WriteLine("Press any key to stop the service.");
  43. Console.ReadLine();
  44. host.Close();
  45.  
  46. }
  47.  
  48. }
  49.  
  50. }

(5) 默认绑定配置:

 在WCF3.0或3.5中,您需要为您的每一个绑定取一个名字,然后您的每个终结点需要指定某个定义好的绑定来进行应用。WCF4.0 引入了默认绑定配置(Default Binding Configurations)。我们可以提供某种类型的绑定的配置,但是如果不把这个绑定配置应用到特定的服务终结点上。WCF会默认把所有匹配该绑定的终结点,全部应用对应的绑定配置。

 例如,我们为wsHttpBinding启用了消息安全模式,并且客户端认证方式为证书,一般的做法是我们定义个绑定配置。代码如下:

  1. <wsHttpBinding>
  2. <binding name="wsHttpBindingSecurity">
  3. <security mode="Message">
  4. <transport clientCredentialType="None">
  5. </transport>
  6. <message clientCredentialType="Certificate"/>
  7. </security>
  8. </binding>
  9. </wsHttpBinding>

  然后在把这个绑定配置应用到特定的服务终结点上,例如:

  1. <endpoint name="endpointService"
  2. address="http://localhost:8100/WCFService"
  3. binding="wsHttpBinding"
  4. contract="WCFService.IWCFService">
  5. </endpoint>

  这样才能对此终结点启用绑定配置的安全要求。但是现在在新的WCF机制下。我们不需要把配置应用到默认的终结点上。简单的配置如下:

  1. <wsHttpBinding>
  2. <binding >
  3. <security mode="Message">
  4. <transport clientCredentialType="None">
  5. </transport>
  6. <message clientCredentialType="Certificate"/>
  7. </security>
  8. </binding>
  9. </wsHttpBinding>

这些配置会作用到匹配wsHttpBinding的默认的服务终结点上。

由于没有证书,所以会出现以下错误信息:

其他信息: “http://localhost:8100/WCFService”处带有协定“"IWCFService"”的 ChannelDispatcher 无法打开其 IchannelListener。

这个错误的解决方式,需要如果将mode改为message方式,这种方式是对消息加密或签名,因此必须要注定证书

  1. <behaviors>
  2. <serviceBehaviors >
  3. <behavior >
  4. <serviceMetadata httpGetEnabled="true" />
  5. <serviceDebug includeExceptionDetailInFaults="false"/>
  6. <serviceCredentials>
  7. <serviceCertificate
  8. findValue="e6 00 c8 f6 93 ce 5c 8f a6 08 a5 c8 0e 09 de 5e 8b 9d 3a 99"
  9.  
  10. x509FindType="FindByThumbprint"
  11. storeLocation="CurrentUser"
  12. storeName="My" />
  13.  
  14. </serviceCredentials>
  15. </behavior>
  16. </serviceBehaviors>
  17. </behaviors>

然后启动Host程序,再来观察一下结果。运行结果如下图:

(6)默认行为配置:

  在WCF3.0或3.5中,您需要为您的每一个行为取一个名字,然后您的每个终结点需要指定某个定义好的行为来进行应用。可以想象,当您有几十个甚至几百个服务同时应用相同的绑定或行为的时候,指定这些名字将成为单纯的体力劳动。为了避免这样的情况,WCF4.0 引入了默认行为配置(Default Behavior Configurations)。WCF允许你定义一个服务行为,该服务行为会默认匹配到该运行在此机器上的全部该解决方案的全部服务(或者终结点)。

  现在在WCF里,以服务行为为例,我们这里的定义不包含名称。配置代码如下:

  1. <serviceBehaviors>
  2. <behavior >
  3. <serviceMetadata httpGetEnabled="true"/>
  4. <serviceDebug includeExceptionDetailInFaults="false"/>
  5. </behavior>
  6. </serviceBehaviors>

  服务的配置非常简单,我们这里只使用一个baseAddress。配置信息如下:

  1. <services>
  2. <service name="WCFService.WCFService" >
  3. <host>
  4. <baseAddresses>
  5. <add baseAddress="http://localhost:8000/"/>
  6. </baseAddresses>
  7. </host>
  8. </service>
  9. </services>

  这里我们也就启用了服务元数据交换,为了检查这个默认服务behavior设置,会不会作用到我们的服务上,现在我们来运行Host,然后在浏览器里查询服务元数据。在WCF3.5里不显示配置,应该是不可以查看的元数据的。这里我们打开浏览器,输入元数据地址,查看信息如下:

默认情况下,这个配置会对所有的服务或终结点起作用。如果我们把配置信息放置在machine.config,则会作用于机器上所有托管的服务或者终结点。如果是app.config,则只影响本托管程序里的服务行为。

最后的配置文件如下:

  1. <?xml version="1.0"?>
  2. <configuration>
  3. <system.web>
  4. <compilation debug="true"/>
  5. </system.web>
  6.  
  7. <!-- When deploying the service library project, the content of the config file must be added to the host's
  8.  
  9. app.config file. System.Configuration does not support config files for libraries. -->
  10.  
  11. <system.serviceModel>
  12.  
  13. <protocolMapping>
  14.  
  15. <add scheme="http" binding="basicHttpBinding"/>
  16. <add scheme="net.tcp" binding="netTcpBinding"/>
  17. <add scheme="net.pipe" binding="netNamedPipeBinding"/>
  18. <add scheme="net.msmq" binding="netMsmqBinding"/>
  19. </protocolMapping>
  20. <services>
  21. <service name="WCFService.WCFService" >
  22. <endpoint name="endpointService"
  23. address="http://localhost:8100/WCFService"
  24. binding="wsHttpBinding"
  25. contract="WCFService.IWCFService">
  26.  
  27. </endpoint>
  28. <!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />-->
  29. <host>
  30.  
  31. <baseAddresses>
  32. <add baseAddress="http://localhost:8000/"/>
  33. <add baseAddress="net.tcp://localhost:8080/"/>
  34. </baseAddresses>
  35. </host>
  36. </service>
  37. </services>
  38. <behaviors>
  39. <serviceBehaviors >
  40. <behavior >
  41. <serviceMetadata httpGetEnabled="true" />
  42. <serviceDebug includeExceptionDetailInFaults="false"/>
  43. <serviceCredentials>
  44. <serviceCertificate
  45. findValue="e6 00 c8 f6 93 ce 5c 8f a6 08 a5 c8 0e 09 de 5e 8b 9d 3a 99"
  46.  
  47. x509FindType="FindByThumbprint"
  48. storeLocation="CurrentUser"
  49. storeName="My" />
  50. </serviceCredentials>
  51. </behavior>
  52. </serviceBehaviors>
  53. </behaviors>
  54. <bindings>
  55. <basicHttpBinding></basicHttpBinding>
  56. <basicHttpContextBinding></basicHttpContextBinding>
  57. <netMsmqBinding></netMsmqBinding>
  58. <netNamedPipeBinding></netNamedPipeBinding>
  59. <webHttpBinding></webHttpBinding>
  60. <wsHttpBinding>
  61. <binding >
  62. <security mode="Message">
  63. <transport clientCredentialType="None">
  64.  
  65. </transport>
  66. <message clientCredentialType="Certificate"/>
  67.  
  68. </security>
  69. </binding>
  70.  
  71. </wsHttpBinding>
  72. <wsDualHttpBinding></wsDualHttpBinding>
  73. </bindings>
  74.  
  75. </system.serviceModel>
  76. <startup>
  77. <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  78. </startup>
  79. </configuration>

WCF学习之旅—WCF4.0中的简化配置功能(十五)的更多相关文章

  1. WCF学习之旅—第三个示例之四(三十)

           上接WCF学习之旅—第三个示例之一(二十七)               WCF学习之旅—第三个示例之二(二十八)              WCF学习之旅—第三个示例之三(二十九)   ...

  2. WCF学习之旅—实现支持REST客户端应用(二十四)

    WCF学习之旅—实现REST服务(二十二) WCF学习之旅—实现支持REST服务端应用(二十三) 在上二篇文章中简单介绍了一下RestFul与WCF支持RestFul所提供的方法,及创建一个支持RES ...

  3. WCF学习之旅—第三个示例之三(二十九)

    上接WCF学习之旅—第三个示例之一(二十七) WCF学习之旅—第三个示例之二(二十八) 在上一篇文章中我们创建了实体对象与接口协定,在这一篇文章中我们来学习如何创建WCF的服务端代码.具体步骤见下面. ...

  4. WCF学习之旅—第三个示例之五(三十一)

       上接WCF学习之旅—第三个示例之一(二十七)               WCF学习之旅—第三个示例之二(二十八)              WCF学习之旅—第三个示例之三(二十九) WCF学习 ...

  5. WCF学习之旅—WCF服务的批量寄宿(十三)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一) WCF学习之旅—WCF ...

  6. WCF学习之旅—WCF服务部署到IIS7.5(九)

    上接   WCF学习之旅—WCF寄宿前的准备(八) 四.WCF服务部署到IIS7.5 我们把WCF寄宿在IIS之上,在IIS中宿主一个服务的主要优点是在发生客户端请求时宿主进程会被自动启动,并且你可以 ...

  7. WCF学习之旅—WCF服务部署到应用程序(十)

    上接  WCF学习之旅—WCF寄宿前的准备(八) WCF学习之旅—WCF服务部署到IIS7.5(九) 五.控制台应用程序宿主 (1) 在解决方案下新建控制台输出项目 ConsoleHosting.如下 ...

  8. WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) 七 WCF服务的Windows 服务程序寄宿 这种方式的服务寄宿,和IIS一样有一个一样 ...

  9. WCF学习之旅—WCF服务的WAS寄宿(十二)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一) 八.WAS宿主 IIS ...

随机推荐

  1. 01.SQLServer性能优化之---水平分库扩展

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 第一次引入文件组的概念:http://www.cnblogs.com/dunitian/ ...

  2. 异步任务队列Celery在Django中的使用

    前段时间在Django Web平台开发中,碰到一些请求执行的任务时间较长(几分钟),为了加快用户的响应时间,因此决定采用异步任务的方式在后台执行这些任务.在同事的指引下接触了Celery这个异步任务队 ...

  3. Jquery的点击事件,三句代码完成全选事件

    先来看一下Js和Jquery的点击事件 举两个简单的例子 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...

  4. 恢复SQL Server被误删除的数据

    恢复SQL Server被误删除的数据 <恢复SQL Server被误删除的数据(再扩展)> 地址:http://www.cnblogs.com/lyhabc/p/4620764.html ...

  5. ABP文档 - Javascript Api - Message

    本节内容: 显示信息 确认 Message API给用户显示一个信息,或从用户那里获取一个确认信息. Message API默认使用sweetalert实现,为使sweetalert正常工作,你应该包 ...

  6. 01.LoT.UI 前后台通用框架分解系列之——小图片背景全屏显示(可自动切换背景)

    LOT.UI分解系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下:https://github.com/du ...

  7. 多线程爬坑之路-Thread和Runable源码解析

    多线程:(百度百科借一波定义) 多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提 ...

  8. ajax请求和aspx返回数据

    ajax请求: $(function () {            $.ajax({                url: "index.aspx?method=send",  ...

  9. c#比较两个数组的差异

    将DataTable中某一列数据直接转换成数组进行比较,使用的Linq,要引用命名空间using System.Linq; string[] arrRate = dtRate.AsEnumerable ...

  10. Android—自定义开关按钮实现

    我们在应用中经常看到一些选择开关状态的配置文件,做项目的时候用的是android的Switch控件,但是感觉好丑的样子………… 个人认为还是自定义的比较好,先上个效果图: