跟我一起从零开始学WCF系列课程(3):配置服务

时间:2022-09-01 08:57:02

本章内容主要包括:

1. 配置服务概述
2. 配置绑定
3 . 配置终结点


1. 配置服务概述
1.1 配置服务

       在设计和实现服务协定后,即可配置服务。在其中可以定义和自定义如何向客户端公开服务,包括指

定可以找到服务的地址(客户端可以找到的服务的地址)、服务用于发送和接收消息的传输模式(http

协议or tcp协议)和消息编码(调用WCF过程中消息是如何编码,全文本格式or优化的编码格式),以及

服务需要的安全类型(需不需要安全控制以及如何实现安全控制)。
1.2 配置服务的类型
      a. 使用配置文件配置(.NET平台的Configuration,部署灵活)
      b. 在代码中强制配置(修改后要重新编译程序)
1.3 实际上,编写配置是WCF 应用程序编程的主要部分。

1.4 使用配置文件配置WCF服务
       a. 通过使用配置文件配置Windows Communication Foundation(WCF) 服务,可提供在部署时而非设计时

提供终结点和服务行为数据的灵活性;
       b. 可使用.NET Framework 配置技术对WCF 服务进行配置。通常情况下,向承载WCF 服务的Internet 信

息服务(IIS) 网站的Web.config 文件添加XML 元素。通过这些元素,可以逐台计算机更改详细信息,例如终结点地址(用于与服务进行通信的实际地址)。此外,WCF 包括几个系统提供的元素,可用于快速选择服务的最基本的功能
       c. WCF 使用.NET Framework 的System.Configuration 配置系统
           -- 使用IIS 来承载服务(web程序)--使用Web.config 文件
           -- 使用任何其他宿主环境(如服务类型、Windows窗体程序、控制台应用程序)—使用或App.config 文件

指定设置。

1.5 可以从上一章中找到WcfServiceLibrary2的配置文件:App.config,可以看到根目录是<configuration>,WCF服务配置放在<system.serviceModel>节点下,该节点包括3个子节点,也就是WCF配置服务的3个基本元素:services(包含endpoint元素),bindings和behaviors,如图3.1所示。 

跟我一起从零开始学WCF系列课程(3):配置服务

图3.1 配置服务三元素

1.5.1 Service元素
每个服务都具有以下属性:
       a. name。指定提供服务协定的实现的类型。这是完全限定名称(命名空间和类型名称)。鉴别服务的唯一性。
       b. behaviorConfiguration。指定一个在behaviors 元素中找到的behavior 元素的名称。指定的行为控制操作,例如服务是否允许模拟。

      <service name="WcfServiceLibrary2.CalculatorService" behaviorConfiguration="WcfServiceLibrary2.Service1Behavior">

 

1.5.2 endpoint元素
每个终结点都需要以下属性表示的地址、绑定和协定:
       a. address。指定服务的统一资源标识符(URI),它可以是一个绝对地址,或是一个相对于服务基址给定的地址。如果设置为空字符串,则指示在创建服务的ServiceHost 时,终结点在指定的

基址上可用。
        b. binding。通常,指定一个类似WsHttpBinding 的系统提供的绑定,但也可以指定一个用户定义的绑定。指定的绑定确定传输协议类型、安全和使用的编码,以及是否支持或启用可靠会话

、事务或流。
       c. bindingConfiguration。如果必须修改绑定的默认值,则可通过在bindings 元素中配置相应的 binding 元素来执行此操作。此属性应赋予与用于更改默认值的binding 元素的name 属性

相同的值。
      d. contract。指定定义协定的接口。这是在由service 元素的name属性指定的公共语言运行库(CLR) 类型中实现的接口。

  <system.serviceModel>
    <bindings />
    <client />
    <services>
      <service name="WcfServiceLibrary2.CalculatorService" behaviorConfiguration="WcfServiceLibrary2.Service1Behavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary2/CalculatorService/"   />
          </baseAddresses>
        </host>
        <!-- Service Endpoints -->
        <!-- Unless fully qualified, address is relative to base address supplied above -->
        <!--默认banding方式是HttpBinding,不支持回调,要改成支持回调的wsDualHttpBinding-->
        <endpoint address=""  binding="wsDualHttpBinding" contract="WcfServiceLibrary2.ICalculatorDuplex" />
 

说明:
address:为空就是使用服务里的基址,即baseAddresses中指定的"http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary2/CalculatorService/";
binding:大部分情况下使用系统提供的默认绑定方式wsHttpBinding,通常使用这种内置的绑定就行了;
contract:我们创建的WCF服务程序的命名空间+接口。

 

1.5.3 binding元素

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="myBindingConfiguration1" closeTimeout="00:01:00" />
        <binding name="myBindingConfiguration2" closeTimeout="00:02:00" />
      </basicHttpBinding>
    </bindings>
    <services>
      <service name="myServiceType">
        <endpoint address="myAddress" binding="basicHttpBinding" bindingConfiguration="myBindingConfiguration1" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

说明:endpoint元素中设置的bindingConfiguration属性就是bindings元素中设置的binding节点的name值:myBindingConfiguration1。

 

1.5.4 behaviors元素

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="myBehavior">
          <callbackDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="NewServiceType">
        <endpoint
         address="myAddress" behaviorConfiguration="myBehavior"
         binding="basicHttpBinding" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

说明:endpoint元素中设置的behaviorConfiguration属性就是behaviors元素中设置的endpointBehaviors节点的name值:myBehavior。

       配置在很多时候取决于特定的部署环境下,需要考虑到的一些因素,根据需要来配置服务。所以使用配置文件配置服务的话,非常具有灵活性,如果这些配置都写在代码里,只要代码一编译就改不了了,管理员就不能改变服务的行为和服务的绑定方式等等。

 

2. 配置绑定
2.1 绑定是用于指定连接到Windows Communication Foundation (WCF)服务终结点所必需的通信详细信息的对象。WCF 服务中的每个终结点都要求正确指定绑定。
2.2 绑定最起码必须指定要使用的传输(如HTTP 或TCP)。还可以通过绑定来设置其他特征,如安全和事务支持。
2.3 绑定中的信息可能非常基本,也可能非常复杂。最基本的绑定仅指定必须用于连接到终结点的传输协议(如HTTP)。一般来说,绑定包含的有关如何连接到终结点的信息属于以下类别中的一种。

    a. 协议:确定要使用的安全机制(加密和认证方式):可靠消息传递功能(加密功能)或事务上下文流设置(事务处理)。
    b. 编码:确定消息编码(例如,文本或二进制)。

    c. 传输:确定要使用的基础传输协议(例如,TCP 或 HTTP)。

2.4 绑定中的信息可能十分复杂,而且某些设置可能与其他设置不兼容。因此,WCF 包含一组系统提供的绑定。这些绑定旨在满足大多数应用程序要求。下面的类表示系统提供的绑定的一些示例:
       a.  BasicHttpBinding:一个HTTP 协议绑定,适用于连接到符合WS-1 基本配置文件规范的Web 服务(例如,基于ASP.NET Web 服务的服务)。--需要与以往的asp.net web 服务交互时设置此绑定,安全性方面差一点,编码格式是文本的;
       b. WSHttpBinding:一个可互操作的绑定,适用于连接到符合WS-*协议的终结点。--有安全处理、安全认证、授权、消息加密;
       c. NetNamedPipeBinding:使用.NET Framework 连接到同一计算机上的其他WCF 终结点。--利用管道通信,性能比较高;
       d. NetMsmqBinding:使用.NET Framework 创建与其他WCF 终结点的排队消息连接。--排队消息的连接,不是实时的,需要排队的。
       大部分情况下,使用这四种预设的绑定方式就可以满足要求了。

2.5 使用自己的绑定
       a. 如果系统提供的绑定都不具有服务应用程序所需的正确功能组合,则可以创建自己的绑定。有两种方法可以实现此目的。
       b. 可以使用CustomBinding 对象从预先存在的绑定元素创建新的绑定 --基于以上预设的绑定值组合成自己的绑定
       c. 也可以通过从Binding 绑定派生来创建完全由用户定义的绑定

2.6 使用绑定
使用绑定需要执行两个基本步骤:
       a. 选择或定义绑定。最简单的方法就是选择WCF 包含的系统提供绑定中的一个,并且通过该绑定的默认设置来使用它。
       b. 创建一个使用所选择或定义的绑定的终结点。

2.7 代码和配置
       a. 可以通过两种方式来定义绑定:通过代码或通过配置。
       b. 这两种方法与您使用的是系统提供的绑定还是自定义绑定无关。通常,使用代码可以使在设计时对绑定的定义拥有完全的控制。
       c. 另一方面,使用配置则使系统管理员或WCF 服务或客户端的用户可以更改绑定的参数,而不必重新编译服务应用程序。由于无法预测用于部署WCF 应用程序的特定计算机要求,因而通常需
要这种灵活性。通过将绑定(和寻址)信息保持在代码外部,人们可以更改这些信息,而不必重新编译或重新部署应用程序。
       d. 请注意,代码中定义的绑定是在配置中指定的绑定之后创建的,这使得代码定义的绑定可以覆盖配置中定义的任何绑定。代码配置的绑定优先级高于配置文件中的绑定。

 

3 配置终结点
3.1 与Windows Communication Foundation (WCF) 服务的所有通信是通过该服务的终结点进行的。利用终结点,客户端可访问WCF 服务提供的功能
3.2 终结点的结构
     – 地址。地址唯一标识终结点并告知潜在客户服务的所在位置
     – 绑定。绑定指定如何与终结点进行通信
     – 服务协定。服务协定概述了终结点向客户端公开的功能
3.3 指定服务的终结点有两种方式
      – 通过使用代码的强制方式或通过配置的声明方式。在代码中定义终结点通常并不可行,因为已部署服务的绑定和地址通常不同于开发服务时使用的绑定和地址。一般而言,使用配置定义服务终结点比使用代码更为可行。使绑定和寻址信息保持在代码之外可以在对它们进行更改后不必重新编译和重新部署应用程序。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="myBindingConfiguration1" closeTimeout="00:01:00" />
        <binding name="myBindingConfiguration2" closeTimeout="00:02:00" />
      </basicHttpBinding>
    </bindings>
    <services>
      <service name="myServiceType">
        <endpoint
        address="myAddress" binding="basicHttpBinding"
        bindingConfiguration="myBindingConfiguration1" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

3.4 终结点地址的定义
3.4.1 终结点的地址由EndpointAddress 类表示,该类包含一个表示服务地址的统一资源定位符(URI),

3.4.2 大多数传输的地址URI 包含四个部分。例如,
“http://www.fabrikam.com:322/mathservice.svc/secureEndpoint”这个URI 具有以下四个部分:
   – 方案:http:
   – 计算机:www.fabrikam.com
   – (可选)端口:322
   – 路径:/mathservice.svc/secureEndpoint
3.4.3 在配置文件中定义终结点地址

  <system.serviceModel>
    <services>
      <service
      name="Microsoft.ServiceModel.Samples.CalculatorService"
      behaviorConfiguration="CalculatorServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/ServiceModelSamples/service"/>
          </baseAddresses>
        </host>
        <endpoint address=""
        binding="wsHttpBinding"
        contract="Microsoft.ServiceModel.Samples.ICalculator" />
        <endpoint address="/test"
        binding="wsHttpBinding"
        contract="Microsoft.ServiceModel.Samples.ICalculator" />
        <endpoint address="net.tcp://localhost:9000/servicemodelsamples/service"
        binding="netTcpBinding"
        contract="Microsoft.ServiceModel.Samples.ICalculator" />
        <!-- the mex endpoint is another reltive address explosed at http://localhost:8000/ServiceModelSamples/service/mex -->
        <endpoint address="mex"
        binding="mexHttpBinding"
        contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>

 

3.4.4 在代码中定义终结点地址

            Uri baseAddress = new Uri("http://localhost:8000/HelloService");
            string address = "http://localhost:8000/HelloService/MyService";
            using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService),
            baseAddress))
            {
                serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(),
                address);
                serviceHost.Open();
                Console.WriteLine("Press <enter> to terminate service");
                Console.ReadLine();
                serviceHost.Close();
            }

 

3.4.5 元数据终结点地址
       a. Windows Communication Foundation (WCF) 服务通过发布一个或多个元数据终结点来发布元数据。
       b. 发布服务元数据之后,可以通过标准协议(如WSMetadataExchange(MEX) 和 HTTP/GET 请求)来使用该元数据。
       c. 元数据终结点类似于其他服务终结点:它们都有一个地址、一个绑定和一个协定,并且它们都可通过配置或使用代码添加到服务主机。
       d. 若要启用发布元数据终结点,必须将ServiceMetadataBehavior 服务行为添加到该服务。默认情况下,WCF 服务不发布元数据终结点,所以必须将它们显式添加到服务才能为服务启用元数据发布。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service
      name="Metadata.Samples.SimpleService"
      behaviorConfiguration="SimpleServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8001/MetadataSample"/>
          </baseAddresses>
        </host>
        <endpoint address=""
        binding="wsHttpBinding"
        contract="Metadata.Samples.ISimpleService" />
        <endpoint address="mex"
        binding="mexHttpBinding"
        contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="SimpleServiceBehavior">
          <serviceMetadata httpGetEnabled="True" policyVersion="Policy12" />
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

其中<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 中binding属性值还可以取以下几类:

mexHttpBinding(对于HTTP 发布)。
mexHttpsBinding(对于HTTPS 发布)。
mexNamedPipeBinding(对于命名管道发布)。
mexTcpBinding(对于TCP 发布)。