65.9K
CodeProject 正在变化。 阅读更多。
Home

WCF 4.0/4.5 中的默认绑定和行为配置、标准终结点和无文件激活

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (10投票s)

2014 年 4 月 25 日

CPOL

12分钟阅读

viewsIcon

76378

downloadIcon

514

本文介绍 WCF 4.0/4.5 中的默认绑定配置、默认行为配置、行为配置中的继承模型、无文件激活和标准终结点。

目录

引言

在我最近的文章(WCF 4.0/4.5 中的默认终结点和默认协议映射)中,我用示例解释了 **WCF 4.0/4.5** 的 **默认终结点** 和 **默认协议映射** 功能。现在,我将在本文中探讨一些新功能,例如 **WCF 4.0/4.5** 附带的 **默认绑定配置**、**默认行为配置**、**行为配置中的继承模型**、**无文件激活** 和 **标准终结点**。

演示服务

对于这篇博文,我创建了一个演示服务 - Greeting。我定义了两个服务协定 IHello IWelcome ,然后通过实现这些服务协定创建了 Greeting 服务。请看下面的代码:

[ServiceContract]
public interface IHello
{
    [OperationContract]
    void Hello(string message);
}

[ServiceContract]
public interface IWelcome
{
    [OperationContract]
    void Welcome(string message);
}

public class Greeting: IHello, IWelcome
{
    public void Hello(string message)
    {
        Console.WriteLine("Hell Mr. {0}", message);
    }

    public void Welcome(string message)
    {
        Console.WriteLine("Welcome Mr. {0}", message); ;
    }
}

我使用自托管技术将 Greeting 服务托管在 Windows 控制台应用程序中。

默认绑定配置

在 **WCF** 中,每个绑定都有内置的默认配置,除非主机应用程序为服务中的特定终结点显式覆盖,否则将使用该默认配置。您可以为某个绑定实例的内置默认配置定义并应用一个显式的绑定配置来覆盖它。

在 **WCF 3.x** 中,您首先定义一个命名的绑定配置,然后通过 bindingConfiguration 属性将其应用于一个或多个终结点定义。假设您想覆盖 BasicHttpbinding 的内置默认配置,以便为服务中的特定终结点支持 **MTOM** 消息编码和基本身份验证类型。为此,您首先需要为 BasicHttpbinding 定义一个命名的绑定配置,然后将其应用于所需的终结点。**WCF 3.x** 中典型的配置文件如下所示:

<system.serviceModel>
<services>
    <service name="WelcomeService.Greeting">
        <endpoint address="" binding="basicHttpBinding" contract="WelcomeService.IWelcome"/>
        <endpoint address="basic" binding="basicHttpBinding" bindingConfiguration="BasicWithMtomPlusBasicAuthentication" contract="WelcomeService.IHello"/>
        <host>
            <baseAddresses>
                <add baseAddress="https://:8080/greeting"/>
            </baseAddresses>
        </host>
    </service>
    </services>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicWithMtomPlusBasicAuthentication" messageEncoding="Mtom">
          <security mode="None">
            <transport proxyCredentialType="Basic"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
</system.serviceModel>

在上文中,为 BasicHttpbinding 配置了一个名为 BasicWithMtomPlusBasicAuthentication 的绑定配置,并将其应用于具有相对地址 **basic** 的终结点。如果在 **WCF 3.x** 的上下文中运行带有上述配置的控制台主机应用程序,您会发现在控制台窗口中,具有相对地址 **basic** 的终结点将显示已覆盖的命名绑定配置 BasicWithMtomPlusBasicAuthentication ,而另一个则仅显示 BasicHttpBinding 的内置默认配置。

值得注意的是,如果您仅定义了一个命名的绑定配置而未将其应用于所需的终结点,则在 **WCF 3.x** 中,覆盖的配置将不会反映在所需的终结点上。因此,只需运行控制台主机应用程序而不将命名绑定配置应用于任何终结点,您就会看到这两个终结点都在控制台窗口中显示 BasicHttpBinding 的内置默认配置。

使用 **WCF 4.0/4.5**,您可以通过在定义新绑定配置时省略绑定配置名称来定义默认绑定配置。如果您为特定绑定定义了一个默认绑定配置,则 **WCF** 将为具有相同绑定且未为其设置显式绑定配置的终结点使用该默认绑定配置。

将此应用程序级别的默认绑定配置与 **WCF 3.5** 进行比较,在 **WCF 3.5** 中,相同绑定的每个终结点都需要设置一个显式的绑定配置名称。

如果您将默认绑定配置添加到 machine.config 文件,它将反映在运行在该计算机上的所有服务中。您也可以通过在应用程序配置文件中添加默认绑定配置来定义应用程序级别的默认绑定配置。

让我们来理解这个概念。对于演示,我已经配置了我们的 Greeting 服务,并带有一个 **http** 基址,并通过 app.config 文件添加了一个相对地址为 basic、使用 BasicHttpbinding IHello 服务协定的终结点。我还定义了一个名为 WithMtom 的命名绑定配置,以便为具有 BasicHttpBinding 的终结点支持 **MTOM** 消息编码,最后通过 bindingConfiguration 属性将其应用于我们具有相对地址 basic 的终结点。我们的控制台主机(app.config)的配置文件如下所示:

<system.serviceModel>
    <services>
      <service name="WelcomeService.Greeting">
        <endpoint address="basic" binding="basicHttpBinding" bindingConfiguration="withMtom"
          contract="WelcomeService.IHello" />
        <host>
          <baseAddresses>
            <add baseAddress="https://:8080/greeting" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <bindings>
      <basicHttpBinding>
        <binding name="withMtom" messageEncoding="Mtom" />
      </basicHttpBinding>
    </bindings>
  </system.serviceModel>

我还调用了 AddDefaultEndpoints 方法来添加默认终结点,以及具有相对地址 basic 的终结点,如下所示:

host.AddDefaultEndpoints();  

现在,如果您运行控制台主机应用程序,您将看到相对地址为 **basic** 的终结点显示了覆盖的命名绑定配置 **WithMtom**,而另外两个默认终结点在控制台窗口中显示了 BasicHttpbinding 的内置默认绑定配置。实际上,BasicHttpbinding 的内置默认绑定配置是从 machine.config 文件中获取的。

现在,我通过省略名称并在上一个配置旁边添加一个默认绑定配置,以便在 app.config 文件中为具有 BasicHttpBinding 的终结点支持 **基本身份验证**,如下所示:

<binding name=""> <!-- no name attribute -->
   <security>
       <transport proxyCredentialType="Basic" /> 
   </security>
</binding>

然后运行控制台主机应用程序,您将看到现在默认终结点显示了覆盖的默认绑定配置,而另一个显示了命名绑定配置。

再做一次实验。只需从相对地址为 **basic** 的终结点中删除命名绑定配置,然后再次运行控制台主机应用程序,您会发现现在所有终结点都显示了之前定义的默认绑定配置。

因此,这是 WCF 4.0/4.5 中的一个很棒的功能。一个重要的注意事项是,不要尝试定义两个默认绑定配置,否则您将收到 ConfigurationErrorsException:“'binding' 类型的子元素已在该配置范围内存在。集合元素在同一配置范围内(例如,同一个 application.config 文件)必须是唯一的。重复的键值: ''”。

默认行为配置

在 **WCF 4.0/4.5** 中,还有一个很好的功能叫做 **默认行为配置**。您可以通过 machine.config 文件或应用程序配置文件定义一个默认行为,该行为可以在同一台机器或同一解决方案中运行的所有服务或终结点之间共享。

在 **WCF 3.x** 中,您必须先定义命名的行为配置,然后通过 “behaviorConfiguration” 属性将其显式应用于服务和终结点。以下是一个典型的 **WCF 3.x** 配置文件:

<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="meta">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="WelcomeService.Greeting" behaviorConfiguration="meta">
        <endpoint address="basic" binding="basicHttpBinding" bindingConfiguration=""
          contract="WelcomeService.IHello" />
        <host>
          <baseAddresses>
            <add baseAddress="https://:8080/greeting" />
          </baseAddresses>
        </host>
      </service>
    </services> 
</system.serviceModel>

但在 **WCF 4.0/4.5** 中,您可以通过省略配置定义中的名称来定义默认行为配置。如果您将这些默认行为添加到 machine.config 文件,它们将反映在同一台机器上托管的所有服务或终结点中。如果您将这些默认行为添加到 app.config 文件,它们仅在主机应用程序的范围内反映。

让我们考虑一个我下面定义的默认行为:

<behaviors>
      <serviceBehaviors>
        <behavior name=""> <!-- no name attribute -->
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
</behaviors>

这是默认服务行为的一个示例,它启用了没有显式行为配置的服务元数据。如果我们运行带有上述默认配置的控制台主机应用程序,我们可以通过服务的 **http** 基址检索服务的 **WSDL** 定义。请看下面的屏幕截图:

如果您还想出于调试目的在 **SOAP** 故障中包含异常详细信息,可以定义一个默认行为,如下所示:

<behavior name=""> <!-- no name attribute -->
   <serviceMetadata httpGetEnabled="true" />
   <serviceDebug includeExceptionDetailInFaults="true" />
</behavior>

行为配置中的继承支持

在 **WCF 4.0/4.5** 中,行为配置还支持继承模型。这意味着如果您使用与 machine.config 中已定义的名称相同的名称定义了一个应用程序特定的行为配置,那么应用程序特定的行为配置将与机器级别的配置合并,并将任何额外的行为添加到派生的复合行为配置中。

让我们来实现这个功能。假设您想隐式启用您机器上所有托管服务的服务元数据,并且进一步想为同一台机器上托管的特定服务显式包含 **SOAP** 故障中的异常详细信息。为了做到这一点,您需要利用我上面解释的行为配置的继承模型。

首先,在 machine.config 文件中的 system.serviceModel 部分下定义一个名为 “metaData” 的命名服务行为,以启用服务元数据,如下所示:

<system.serviceModel>
 <behaviors>
      <serviceBehaviors>
        <behavior name="metaData">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
 </behaviors>

... 

其次,在特定服务的 app.config 文件中使用与您已在 machine.config 文件中定义的名称相同的名称,定义另一个名为 “metaData” 的命名服务行为,如下所示:

<behaviors>
      <serviceBehaviors>
        <behavior name="metaData">
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
/behaviors>

   ...

然后,像下面这样将名为 “metaData” 的服务行为应用于您的服务:

 <services>
      <service name="WelcomeService.Greeting" behaviorConfiguration="metaData">
        <endpoint address="basic" binding="basicHttpBinding" contract="WelcomeService.IHello" />
        <host>
          <baseAddresses>
            <add baseAddress="https://:8080/greeting" />
          </baseAddresses>
        </host>
      </service>
 </services>  

现在,如果我们运行带有上述命名服务行为定义的控制台主机应用程序,我们可以通过服务的 **http** 基址检索我们的服务(Greeting)的 **WSDL** 定义。我们还可以从控制台主机窗口验证 includeExceptionDetailInFaults 的值为 true,从而确保异常详细信息将包含在 **SOAP** 故障中。请看下面的屏幕截图:


因此,在这里您已经看到,在运行时,应用程序特定的行为配置通过将任何额外的行为添加到派生的复合行为配置中,与机器级别的配置进行了合并。

无文件激活

正如您所知,借助 **.svc** 文件,可以轻松地在 **IIS/WAS** 中托管 **WCF** 服务。但是,还有一种更简单的方法可以公开 **WCF** 服务,即在 **Web.config** 中定义虚拟激活终结点,从而无需物理 **.svc** 文件。

在 **WCF 4.0/4.5** 中,您可以在 web.config 中定义虚拟服务激活终结点,这些终结点映射到您的服务类型。这使得在无需维护物理 **.svc** 文件的情况下激活 **WCF** 服务成为可能。这就是所谓的 **无文件激活**。

让我们托管我们的 Greeting 服务到 **IIS** 以理解这个概念。我创建了一个演示 **WCF 服务网站**,并将 **WelcomeService** 项目(**WCF** 项目)的引用添加到了它,然后删除了 **service.svc** 文件。然后,我在 web.config 文件中定义了一个激活终结点,如下所示:

<serviceHostingEnvironment >
      <serviceActivations>
        <add relativeAddress="Greeting.svc" service="WelcomeService.Greeting"/>
      </serviceActivations>      
</serviceHostingEnvironment>

通过上述配置,可以使用 “Greeting.svc” 的相对路径(相对于 **Web** 应用程序的基址)激活 Greeting 服务。

最后,我将 Greeting 服务托管在 **IIS** 中,而没有 **.svc** 文件。现在您可以浏览到 **https:///greetings/Greeting.svc**,而实际上没有物理 **.svc** 文件。请看下面的屏幕截图:

标准终结点

这是 **WCF 4.0/4.5** 中的另一个新功能。标准终结点是 **WCF 4.0/4.5** 提供的一个通用的预配置终结点定义。标准终结点使我们能够定义一个通常不会更改的终结点配置,但如果需要,也可以进行更改。

下表(来自 msdn)包含了 **WCF 4.0/4.5** 附带的标准终结点,描述了最常见 WCF 功能和通信场景的标准终结点定义:

元素 描述

<announcementEndpoint>

定义了一个具有固定公告协定的标准终结点。服务可以在打开或关闭时可选地通过发送在线和离线公告消息来声明其可用性。Windows Communication Foundation (WCF) 服务在 <serviceDiscovery> 元素中指定公告终结点,并使用 AnnouncementClient 执行公告。希望监听其他服务公告的客户端实际上充当 WCF 服务;因此,您必须在 <services> 部分中为该客户端配置公告终结点。

<discoveryEndpoint>

定义了一个具有固定发现协定的标准终结点。添加到服务配置时,它指定监听发现消息的位置。添加到客户端配置时,它指定发送发现查询的位置。

<dynamicEndpoint>

此配置元素定义了一个标准终结点,其中包含使应用程序能够充当客户端程序的信息,该程序可以在运行时动态查找终结点地址。

<mexEndpoint>

定义了一个具有固定 IMetadataExchange 协定的标准终结点。由于所有元数据交换终结点都将 IMetadataExchange 指定为其协定,因此您可以使用此标准终结点,而无需自己定义一个。

<udpAnnoucementEndpoint>

定义了一个供服务通过 UDP 绑定发送公告消息的标准终结点。它具有固定的协定,并支持两个发现版本。此外,它具有固定的 UDP 绑定和 WS-Discovery 规范中指定的默认地址值(WS-Discovery April 2005 或 WS-Discovery version 1.1)。您可以指定用于发送和接收公告消息的多播地址。

<udpDiscoveryEndpoint>

定义了一个通过 UDP 多播绑定预先配置用于发现操作的标准终结点。此终结点具有固定的协定,并支持两个 WS-Discovery 协议版本。此外,它具有固定的 UDP 绑定和 WS-Discovery 规范(WS-Discovery April 2005 或 WS-Discovery V1.1)中指定的默认地址。

<webHttpEndpoint>

定义了一个具有固定 <webHttpBinding> 绑定的标准终结点,该绑定会自动添加 <webHttp> 行为。在编写 REST 服务时使用此终结点。

<webScriptEndpoint>

定义了一个具有固定 <webHttpBinding> 绑定的标准终结点,该绑定会自动添加 <enableWebScript> 行为。当编写由 ASP.NET AJAX 应用程序调用的服务时,使用此终结点。

<workflowControlEndpoint>

定义一个用于控制工作流实例执行(创建、运行、挂起、终止等)的标准终结点。

您可以通过简单地按需引用上述标准终结点来利用它们。 您的服务配置。

让我们来看一个例子。假设您想为您的服务主机配置一个 **MEX** 终结点。在这种情况下,您始终需要指定 IMetadataExchange 服务协定,并且很可能使用 **HTTP** 协议(您也可以使用 **TCP/NamedPipe/HTTPS**)。因此,典型的 **MEX** 终结点将是:

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />

但是,使用 **WCF 4.0/4.5**,您可以使用元数据交换的标准终结点定义 “mexEndpoint” 来配置您的服务主机,使用新的 “kind” 属性。 <endpoint> 元素,如下所示:

<endpoint address="mex" kind="mexEndpoint" /> 

现在,如果我们运行带有上述元数据交换标准终结点定义的我们的服务控制台主机应用程序,您可以在控制台窗口中看到 **MEX** 终结点:

您可以使用 svcutil.exe 以如下方式生成配置文件和包含客户端类的代码文件:

svcutil.exe https://:8080/greeting/mex

虽然标准终结点隐藏了大多数配置细节,但可能存在一些场景,其中一个人希望使用具有略有不同配置的标准终结点。这可以通过遵循以下两个步骤来覆盖标准终结点配置来完成。

首先,您需要使用 <standardEndpoints> 部分来覆盖标准终结点配置。其次,您需要通过 endpointConfiguration 属性在定义新的 <endpoint> 时引用该覆盖的标准终结点配置,如下所示:

<services>
      <service name="WelcomeService.Greeting">
        <endpoint address="basic" binding="basicHttpBinding" contract="WelcomeService.IHello" />
        <endpoint address="mex" kind="mexEndpoint" endpointConfiguration="lock" />
        <host>
          <baseAddresses>
            <add baseAddress="https://:8080/greeting" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <standardEndpoints>
      <mexEndpoint>
        <standardEndpoint name="lock"  lockItem="true" />
      </mexEndpoint>
    </standardEndpoints>

结论

因此,在这篇文章中,我已尽最大努力解释了 **WCF 4.0/4.5** 中与默认绑定/行为配置、行为配置中的继承模型、无文件激活和标准终结点相关的概念。在下一篇文章中,我将介绍更多 **WCF** 主题。编码愉快!

© . All rights reserved.