元数据体系结构概述

Windows Communication Foundation (WCF) 提供了用于导出、发布、检索和导入服务元数据的丰富的基础结构。 WCF 服务使用元数据来描述如何与服务的终结点进行交互,以便工具(如 Svcutil.exe)可以自动生成客户端代码来访问服务。

构成 WCF 元数据基础结构的大多数类型驻留在 System.ServiceModel.Description 命名空间中。

WCF 使用 ServiceEndpoint 类描述服务中的终结点。 可以使用 WCF 为服务终结点生成元数据或者导入服务元数据以生成 ServiceEndpoint 实例。

WCF 将服务的元数据表示为 MetadataSet 类型的实例,其结构被强附加到在 WS-MetadataExchange 中定义的元数据序列化格式。 MetadataSet 类型将实际的服务元数据(如 Web 服务描述语言 (WSDL) 文档、XML 架构文档或 WS-Policy 表达式)作为 MetadataSection 实例的集合绑定。 每个 System.ServiceModel.Description.MetadataSection 实例都包含特定的元数据方言和标识符。 System.ServiceModel.Description.MetadataSection 在其 MetadataSection.Metadata 属性中可能包含以下项:

System.ServiceModel.Description.MetadataReference 实例指向另一个元数据交换 (MEX) 终结点,而 System.ServiceModel.Description.MetadataLocation 实例指向使用 HTTP URL 的元数据文档。 WCF 支持使用 WSDL 文件来描述服务终结点、服务协定、绑定、消息交换模式、消息以及服务实现的故障消息。 服务使用的数据类型在 WSDL 文档中使用 XML 架构进行描述。 有关详细信息,请参阅架构导入和导出。 可以使用 WCF 导出和导入服务行为的 WSDL 扩展、协定行为和扩展服务功能的绑定元素。 有关详细信息,请参阅导出 WCF 扩展的自定义元数据

导出服务元数据

在 WCF 中,“元数据导出”是描述服务终结点,并将它们投影到客户端可用来了解如何使用服务的并行标准化表示的过程。 若要从 ServiceEndpoint 实例导出元数据,请使用 MetadataExporter 抽象类的实现。 System.ServiceModel.Description.MetadataExporter 实现生成包装在 MetadataSet 实例中的元数据。

System.ServiceModel.Description.MetadataExporter 类提供了一个框架,用于生成描述终结点绑定的功能和需求及其关联操作、消息和错误的策略表达式。 在 PolicyConversionContext 实例中可捕获这些策略表达式。 然后 System.ServiceModel.Description.MetadataExporter 实现可以将这些策略表达式附加到它生成的元数据。

当生成供 System.ServiceModel.Description.MetadataExporter 实现使用的 System.ServiceModel.Channels.BindingElement 对象时,IPolicyExportExtension 调入在 ServiceEndpoint 的绑定中实现 PolicyConversionContext 接口的每个 System.ServiceModel.Description.MetadataExporter。 通过在 IPolicyExportExtension 类型的自定义实现上实现 BindingElement 接口,可以导出新策略断言。

WsdlExporter 类型是 WCF 所包含的 System.ServiceModel.Description.MetadataExporter 抽象类的实现。 WsdlExporter 类型使用附加的策略表达式生成 WSDL 元数据。

若要导出自定义 WSDL 元数据或终结点行为的 WSDL 扩展、协定行为或服务终结点中的绑定元素,可以实现 IWsdlExportExtension 接口。 在生成 WSDL 文档时,WsdlExporter 为实现 ServiceEndpoint 接口的绑定元素、操作行为、协定行为和终结点行为查看 IWsdlExportExtension 实例。

发布服务元数据

WCF 服务通过公开一个或多个元数据终结点来发布元数据。 使用标准协议(如 MEX 和 HTTP/GET 请求)发布服务元数据可使服务元数据变得可用。 元数据终结点与其他服务终结点类似,都具有地址、绑定和协定。 可以在配置中或在代码中将元数据终结点添加到服务主机。

若要发布 WCF 服务的元数据终结点,必须首先将 ServiceMetadataBehavior 服务行为的实例添加到服务。 将 System.ServiceModel.Description.ServiceMetadataBehavior 实例添加到服务,使服务增添了通过公开一个或多个元数据终结点发布元数据的功能。 添加 System.ServiceModel.Description.ServiceMetadataBehavior 服务行为后,可以公开支持 MEX 协议的元数据终结点或响应 HTTP/GET 请求的元数据终结点。

若要添加使用 MEX 协议的元数据终结点,请将服务终结点添加到使用名为 IMetadataExchange 的服务协定的服务主机。WCF 定义具有此服务协定名称的 IMetadataExchange 接口。 WS-MetadataExchange 终结点或 MEX 终结点可以使用由 MetadataExchangeBindings 类上静态工厂方法公开的四个默认绑定之一,以匹配 WCF 工具(如 Svcutil.exe)使用的默认绑定。 也可以使用自定义绑定配置 MEX 元数据终结点。

ServiceMetadataBehavior 使用 System.ServiceModel.Description.WsdlExporter 来导出服务中所有服务终结点的元数据。 有关从服务导出元数据的详细信息,请参阅导出和导入元数据

通过将 ServiceMetadataBehavior 实例作为服务主机的扩展添加,ServiceMetadataExtension 增强了服务主机。 System.ServiceModel.Description.ServiceMetadataExtension 提供了元数据发布协议的实现。 还可以通过访问 Metadata 属性来使用 System.ServiceModel.Description.ServiceMetadataExtension 在运行时获取服务的元数据。

注意

如果在应用程序配置文件中添加 MEX 终结点,然后尝试在代码中向服务主机添加 ServiceMetadataBehavior,则会得到以下异常:

System.InvalidOperationException: 在服务 Service1 实现的协定列表中找不到协定名称“ImetadataExchange”。 将 ServiceMetadataBehavior 添加到配置文件或直接添加到 ServiceHost,以启用对该协定的支持。

通过在配置文件中 ServiceMetadataBehavior 或在代码中同时添加终结点和 ServiceMetadataBehavior,可以解决此问题。

有关在应用程序配置文件中添加 ServiceMetadataBehavior 的示例,请参见入门。 有关在代码中添加 ServiceMetadataBehavior 的示例,请参见自承载示例。

注意

当发布公开两个不同服务协定(两个服务协定包含具有相同名称的操作)的服务的元数据时,会引发异常。 例如,如果有一个服务公开了一个名为 ICarService 的服务协定,该服务协定具有一个 Get(Car c) 操作,且同一服务还公开了一个名为 IBookService 的服务协定,该服务协定具有一个 Get(Book b) 操作,则当生成该服务的元数据时,会引发异常或显示错误消息。 若要解决此问题,请执行下列操作之一:

  • 重命名其中的一项操作。
  • Name 设置为其他名称。
  • 使用 Namespace 属性将其中一项操作的命名空间设置为其他命名空间。

检索服务元数据

WCF 可以使用标准化协议(如 WS-MetadataExchange 和 HTTP)检索服务元数据。 这两种协议均受 MetadataExchangeClient 类型支持。 通过提供地址和可选绑定,使用 System.ServiceModel.Description.MetadataExchangeClient 类型检索服务元数据。 由 System.ServiceModel.Description.MetadataExchangeClient 实例使用的绑定可以是 MetadataExchangeBindings 静态类中的默认绑定之一、用户提供的绑定或从 IMetadataExchange 协定的终结点配置加载的绑定。 System.ServiceModel.Description.MetadataExchangeClient 也可以使用 HttpWebRequest 类型来解析 HTTP URL 对元数据的引用。

默认情况下,System.ServiceModel.Description.MetadataExchangeClient 实例与单个 ChannelFactoryBase 实例关联。 通过重写 ChannelFactoryBase 虚拟方法,您可以更改或替换由 System.ServiceModel.Description.MetadataExchangeClient 使用的 GetChannelFactory 实例。 同样,通过重写 System.Net.HttpWebRequest 虚拟方法,可以更改或替换由 System.ServiceModel.Description.MetadataExchangeClient 使用的 MetadataExchangeClient.GetWebRequest 实例以发出 HTTP/GET 请求。

通过使用 Svcutil.exe 工具并传递“/target:metadata”开关和地址,你可以使用 WS-MetadataExchange 或 HTTP/GET 请求检索服务元数据。 Svcutil.exe 下载指定位置的元数据并将文件保存到磁盘。 Svcutil.exe 在内部使用 System.ServiceModel.Description.MetadataExchangeClient 实例,并加载其名称与传递到 Svcutil.exe 的地址的方案(如果存在)匹配的 MEX 终结点配置(从应用程序配置文件)。 否则,Svcutil.exe 默认使用由 MetadataExchangeBindings 静态工厂类型定义的绑定之一。

导入服务元数据

在 WCF 中,元数据导入是从服务的元数据生成服务或其组成部分的抽象表示的过程。 例如,WCF 可以从服务的 WSDL 文档导入 ServiceEndpoint 实例、Binding 实例或 ContractDescription 实例。 要在 WCF 中导入服务元数据,请使用 MetadataImporter 抽象类的实现。 派生自 System.ServiceModel.Description.MetadataImporter 类的类型实现对导入元数据格式的支持,这些元数据格式利用了 WCF 中的 WS-Policy 导入逻辑。

System.ServiceModel.Description.MetadataImporter 实现收集附加到 PolicyConversionContext 对象中服务元数据的策略表达式。 然后,通过在 System.ServiceModel.Description.MetadataImporter 属性中调用 IPolicyImportExtension 接口的实现,PolicyImportExtensions 在导入元数据的过程中处理策略。

通过将自己的 System.ServiceModel.Description.MetadataImporter 接口实现添加到 IPolicyImportExtension 实例上的 PolicyImportExtensions 集合,可以添加对将新策略断言导入到 System.ServiceModel.Description.MetadataImporter 的支持。 或者,可以在客户端应用程序配置文件中注册策略导入扩展。

System.ServiceModel.Description.WsdlImporter 类型是 WCF 所包含的 System.ServiceModel.Description.MetadataImporter 抽象类的实现。 System.ServiceModel.Description.WsdlImporter 类型可以导入含有附加策略(这些策略捆绑在 MetadataSet 对象中)的 WSDL 元数据。

通过实现 IWsdlImportExtension 接口,然后将实现添加到 WsdlImportExtensions 实例上的 System.ServiceModel.Description.WsdlImporter 属性,可以添加对导入 WSDL 扩展的支持。 System.ServiceModel.Description.WsdlImporter 还可以加载在客户端应用程序配置文件中注册的 System.ServiceModel.Description.IWsdlImportExtension 接口的实现。

动态绑定

如果终结点的绑定更改,或者希望为使用相同协定但具有不同绑定的终结点创建一个通道,则可以动态更新用来为服务终结点创建通道的绑定。 可以使用 MetadataResolver 静态类在运行时为实现特定协定的服务终结点检索和导入元数据。 然后可以使用导入的 System.ServiceModel.Description.ServiceEndpoint 对象为所需终结点创建客户端或通道工厂。

另请参阅