Metadata Architecture Overview
Windows Communication Foundation (WCF) provides a rich infrastructure for exporting, publishing, retrieving, and importing service metadata. WCF services use metadata to describe how to interact with the service's endpoints so that tools, such as Svcutil.exe, can automatically generate client code for accessing the service.
Most of the types that make up the WCF metadata infrastructure reside in the System.ServiceModel.Description namespace.
WCF represents the metadata for a service as an instance of the MetadataSet type, the structure of which is strongly tied to the metadata serialization format defined in WS-MetadataExchange. The MetadataSet type bundles the actual service metadata, such as Web Services Description Language (WSDL) documents, XML schema documents, or WS-Policy expressions, as a collection of MetadataSection instances. Each System.ServiceModel.Description.MetadataSection instance contains a specific metadata dialect and an identifier. A System.ServiceModel.Description.MetadataSection can contain the following items in its MetadataSection.Metadata property:
A System.ServiceModel.Description.MetadataReference instances point to another metadata exchange (MEX) endpoint and System.ServiceModel.Description.MetadataLocation instances point to a metadata document using an HTTP URL. WCF supports using WSDL documents to describe service endpoints, service contracts, bindings, message exchange patterns, messages and fault messages implemented by a service. Data types used by the service are described in WSDL documents using XML schema. For more information, see Schema Import and Export. You can use WCF to export and import WSDL extensions for service behavior, contract behaviors, and binding elements that extend the functionality of a service. For more information, see Exporting Custom Metadata for a WCF Extension.
Exporting Service Metadata
In WCF, metadata export is the process of describing service endpoints and projecting them into a parallel, standardized representation that clients can use to understand how to use the service. To export metadata from ServiceEndpoint instances, use an implementation of the MetadataExporter abstract class. A System.ServiceModel.Description.MetadataExporter implementation generates metadata that is encapsulated in a MetadataSet instance.
The System.ServiceModel.Description.MetadataExporter class provides a framework for generating policy expressions that describe the capabilities and requirements of an endpoint binding and its associated operations, messages, and faults. These policy expressions are captured in a PolicyConversionContext instance. A System.ServiceModel.Description.MetadataExporter implementation can then attach these policy expressions to the metadata it generates.
The System.ServiceModel.Description.MetadataExporter calls into each System.ServiceModel.Channels.BindingElement that implements the IPolicyExportExtension interface in the binding of a ServiceEndpoint when generating a PolicyConversionContext object for the System.ServiceModel.Description.MetadataExporter implementation to use. You can export new policy assertions by implementing the IPolicyExportExtension interface on your custom implementations of the BindingElement type.
The WsdlExporter type is the implementation of the System.ServiceModel.Description.MetadataExporter abstract class included with WCF. The WsdlExporter type generates WSDL metadata with attached policy expressions.
To export custom WSDL metadata or WSDL extensions for endpoint behaviors, contract behaviors, or binding elements in a service endpoint, you can implement the IWsdlExportExtension interface. The WsdlExporter looks at a ServiceEndpoint instance for binding elements, operation behaviors, contract behaviors, and endpoint behaviors that implement the IWsdlExportExtension interface when generating the WSDL document.
Publishing Service Metadata
WCF services publish metadata by exposing one or more metadata endpoints. Publishing service metadata makes service metadata available using standardized protocols, such as MEX and HTTP/GET requests. Metadata endpoints are similar to other service endpoints in that they have an address, a binding, and a contract. You can add metadata endpoints to a service host in configuration or in code.
To publish metadata endpoints for a WCF service, you must first add an instance of the ServiceMetadataBehavior service behavior to the service. Adding a System.ServiceModel.Description.ServiceMetadataBehavior instance to your service augments your service with the ability to publish metadata by exposing one or more metadata endpoints. Once you add the System.ServiceModel.Description.ServiceMetadataBehavior service behavior you can then expose metadata endpoints that support the MEX protocol or metadata endpoints that respond to HTTP/GET requests.
To add metadata endpoints that use the MEX protocol, add service endpoints to your service host that use the service contract named IMetadataExchange.WCF defines the IMetadataExchange interface that has this service contract name. WS-MetadataExchange endpoints, or MEX endpoints, can use one of the four default bindings exposed by the static factory methods on the MetadataExchangeBindings class to match the default bindings used by WCF tools, such as Svcutil.exe. You can also configure MEX metadata endpoints using a custom binding.
The ServiceMetadataBehavior uses a System.ServiceModel.Description.WsdlExporter to export metadata for all service endpoints in your service. For more information about exporting metadata from a service, see Exporting and Importing Metadata.
The ServiceMetadataBehavior augments your service host by adding a ServiceMetadataExtension instance as an extension to your service host. The System.ServiceModel.Description.ServiceMetadataExtension provides the implementation for the metadata publishing protocols. You can also use the System.ServiceModel.Description.ServiceMetadataExtension to get the service's metadata at runtime by accessing the Metadata property.
If you add a MEX endpoint in your application configuration file and then attempt to add the ServiceMetadataBehavior to your service host in code you get the following exception:
System.InvalidOperationException: The contract name 'IMetadataExchange' could not be found in the list of contracts implemented by the service Service1. Add a ServiceMetadataBehavior to the configuration file or to the ServiceHost directly to enable support for this contract.
When publishing metadata for a service that exposes two different service contracts in which each contain an operation of the same name an exception is thrown. For example, if you have a service that exposes a service contract called ICarService that has an operation Get(Car c) and the same service exposes a service contract called IBookService that has an operation Get(Book b), an exception is thrown or an error message is displayed when generating the service's metadata. To work around this issue do one of the following:
Retrieving Service Metadata
WCF can retrieve service metadata using standardized protocols such as WS-MetadataExchange and HTTP. Both of these protocols are supported by the MetadataExchangeClient type. You retrieve service metadata using the System.ServiceModel.Description.MetadataExchangeClient type by providing an address and an optional binding. The binding used by a System.ServiceModel.Description.MetadataExchangeClient instance can be one of the default bindings from the MetadataExchangeBindings static class, a user-supplied binding, or a binding loaded from an endpoint configuration for the
IMetadataExchange contract. The System.ServiceModel.Description.MetadataExchangeClient can also resolve HTTP URL references to metadata using the HttpWebRequest type.
By default, a System.ServiceModel.Description.MetadataExchangeClient instance is tied to a single ChannelFactoryBase instance. You can change or replace the ChannelFactoryBase instance used by a System.ServiceModel.Description.MetadataExchangeClient by overriding the GetChannelFactory virtual method. Similarly, you can change or replace the System.Net.HttpWebRequest instance used by a System.ServiceModel.Description.MetadataExchangeClient to make HTTP/GET requests by overriding the MetadataExchangeClient.GetWebRequest virtual method.
You can retrieve service metadata using WS-MetadataExchange or HTTP/GET requests by using the Svcutil.exe tool and passing the /target:metadata switch and an address. Svcutil.exe downloads the metadata at the specified address and saves the files to disk. Svcutil.exe uses a System.ServiceModel.Description.MetadataExchangeClient instance internally and loads an MEX endpoint configuration (from the application configuration file) whose name matches the scheme of the address passed to Svcutil.exe, if one exists. Otherwise, Svcutil.exe defaults to using one of the bindings defined by the MetadataExchangeBindings static factory type.
Importing Service Metadata
In WCF, metadata import is the process of generating an abstract representation of a service or its component parts from its metadata. For example, WCF can import ServiceEndpoint instances, Binding instances or ContractDescription instances from a WSDL document for a service. To import service metadata in WCF, use an implementation of the MetadataImporter abstract class. Types that derive from the System.ServiceModel.Description.MetadataImporter class implement support for importing metadata formats that take advantage of the WS-Policy import logic in WCF.
A System.ServiceModel.Description.MetadataImporter implementation collects the policy expressions attached to the service metadata in a PolicyConversionContext object. The System.ServiceModel.Description.MetadataImporter then processes the policies as part of importing the metadata by calling the implementations of the IPolicyImportExtension interface in the PolicyImportExtensions property.
You can add support for importing new policy assertions to a System.ServiceModel.Description.MetadataImporter by adding your own implementation of the IPolicyImportExtension interface to the PolicyImportExtensions collection on a System.ServiceModel.Description.MetadataImporter instance. Alternatively, you can register your policy import extension in your client application configuration file.
The System.ServiceModel.Description.WsdlImporter type is the implementation of the System.ServiceModel.Description.MetadataImporter abstract class included with WCF. The System.ServiceModel.Description.WsdlImporter type imports WSDL metadata with attached policies that are bundled in a MetadataSet object.
You can add support for importing WSDL extensions by implementing the IWsdlImportExtension interface and then adding your implementation to the WsdlImportExtensions property on your System.ServiceModel.Description.WsdlImporter instance. The System.ServiceModel.Description.WsdlImporter can also load implementations of the System.ServiceModel.Description.IWsdlImportExtension interface registered in your client application configuration file.
You can dynamically update the binding that you use to create a channel to a service endpoint in the event that the binding for the endpoint changes or you want to create a channel to an endpoint that uses the same contract but has a different binding. You can use the MetadataResolver static class to retrieve and import metadata at runtime for service endpoints that implement a specific contract. You can then use the imported System.ServiceModel.Description.ServiceEndpoint objects to create a client or channel factory to the desired endpoint.