How to: Publish Metadata for a Service Using a Configuration File
This is one of two how-to topics that demonstrate publishing metadata for a Windows Communication Foundation (WCF) service. There are two ways to specify how a service should publish metadata, using a configuration file and using code. This topic shows how to publish metadata for a service using a configuration file.
Caution
This topic shows how to publish metadata in an unsecure manner. Any client can retrieve the metadata from the service. If you require your service to publish metadata in a secure manner, see Custom Secure Metadata Endpoint.
For more information about publishing metadata in code, see How to: Publish Metadata for a Service Using Code. Publishing metadata allows clients to retrieve the metadata using a WS-Transfer GET request or an HTTP/GET request using the ?wsdl
query string. To be sure that the code is working, create a basic WCF service. For simplicity, a basic self-hosted service is provided in the following code.
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace Metadata.Samples
{
[ServiceContract]
public interface ISimpleService
{
[OperationContract]
string SimpleMethod(string msg);
}
class SimpleService : ISimpleService
{
public string SimpleMethod(string msg)
{
Console.WriteLine("The caller passed in " + msg);
return "Hello " + msg;
}
}
class Program
{
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(SimpleService),
new Uri("http://localhost:8001/MetadataSample"));
try
{
// Open the service host to accept incoming calls
host.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
// Close the ServiceHostBase to shutdown the service.
host.Close();
}
catch (CommunicationException commProblem)
{
Console.WriteLine("There was a communication problem. " + commProblem.Message);
Console.Read();
}
}
}
}
This service is a self-hosted service, which is configured using a configuration file. The following configuration file serves as a starting point.
<configuration>
<system.serviceModel>
<services>
<service name="Metadata.Example.SimpleService">
<endpoint address=""
binding="basicHttpBinding"
contract="Metadata.Example.ISimpleService" />
</service>
</services>
<behaviors>
</behaviors>
</system.serviceModel>
</configuration>
To publish metadata for a WCF service using an application configuration file
Within the App.config file, after the closing
</services>
element, create a<behaviors>
element.Within the
<behaviors>
element, add a<serviceBehaviors>
element.Add a
<behavior>
element to the<serviceBehaviors>
element and specify a value for thename
attribute of the<behavior>
element.Add a
<serviceMetadata>
element to the<behavior>
element. Set thehttpGetEnabled
attribute totrue
and thepolicyVersion
attribute to Policy15.httpGetEnabled
allows the service to respond to metadata requests made by an HTTP GET request.policyVersion
tells the service to conform to WS-Policy 1.5 when generating metadata.Add a
behaviorConfiguration
attribute to the<service>
element and specify thename
attribute of the<behavior>
element added in step 1, as shown in the following code example.<services> <service name="Metadata.Example.SimpleService" behaviorConfiguration="SimpleServiceBehavior"> ... </service> </services> <behaviors> <serviceBehaviors> <behavior name="SimpleServiceBehavior"> <serviceMetadata httpGetEnabled="True" policyVersion="Policy15" /> </behavior> </serviceBehaviors> </behaviors>
Add one or more
<endpoint>
elements with the contract set toIMetadataExchange
, as shown in the following code example.<services> <service name="Metadata.Example.SimpleService" behaviorConfiguration="SimpleServiceBehavior"> <endpoint address="" binding="wsHttpBinding" contract="Metadata.Example.ISimpleService" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services>
For the metadata endpoints added in the previous step, set the
binding
attribute to one of the following:mexHttpBinding
for HTTP publication.mexHttpsBinding
for HTTPS publication.mexNamedPipeBinding
for named pipe publication.mexTcpBinding
for TCP publication.
For the metadata endpoints added in a previous step, set the address equal to:
An empty string to use the host application's base address as the publication point if the base address is the same as the metadata binding.
A relative address if the host application has a base address.
An absolute address.
Build and run the console application.
Browse to the base address of the service (
http://localhost:8001/MetadataSample
in this sample) and verify that the metadata publishing is turned on. If not, a message at the top of the resulting page displays: "Metadata publishing for this service is currently disabled."
To use default endpoints
To configure metadata on a service that uses default endpoints, specify the ServiceMetadataBehavior in the configuration file as in the previous example, but do not specify any endpoints. The configuration file would then look like this.
<configuration> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="SimpleServiceBehavior"> <serviceMetadata httpGetEnabled="True" policyVersion="Policy12" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
Because the service has a ServiceMetadataBehavior with the
httpGetEnabled
set totrue
, the service has publishing metadata enabled, and because no endpoints were explicitly added, the runtime adds the default endpoints. For more information about default endpoints, bindings, and behaviors, see Simplified Configuration and Simplified Configuration for WCF Services.
Example
The following code example shows the implementation of a basic WCF service and the configuration file that publishes metadata for the service.
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace Metadata.Samples
{
[ServiceContract]
public interface ISimpleService
{
[OperationContract]
string SimpleMethod(string msg);
}
class SimpleService : ISimpleService
{
public string SimpleMethod(string msg)
{
Console.WriteLine("The caller passed in " + msg);
return "Hello " + msg;
}
}
class Program
{
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(SimpleService),
new Uri("http://localhost:8001/MetadataSample"));
try
{
// Open the service host to accept incoming calls
host.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
// Close the ServiceHostBase to shutdown the service.
host.Close();
}
catch (CommunicationException commProblem)
{
Console.WriteLine("There was a communication problem. " + commProblem.Message);
Console.Read();
}
}
}
}
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="SimpleServiceBehavior">
<serviceMetadata httpGetEnabled="True" policyVersion="Policy12" />
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>