如何:使用代码发布服务的元数据

这是讨论发布 Windows Communication Foundation (WCF) 服务的元数据的两个帮助主题之一。有两种方式可以指定服务应如何发布元数据:使用配置文件和使用代码。本主题演示如何使用代码发布服务的元数据。

Aa738489.Caution(zh-cn,VS.100).gif警告:
本主题演示如何以不安全的方式发布元数据。任何客户端都可以检索服务的元数据。如果您要求服务以安全的方式发布元数据,请参见自定义安全元数据终结点

有关在配置文件中发布元数据的更多信息,请参见如何:使用配置文件发布服务的元数据。通过发布元数据,客户端可以使用 WS-Transfer GET 请求或使用 ?wsdl 查询字符串的 HTTP/GET 来检索元数据。若要确保代码能够工作,必须创建一个基本的 WCF 服务。在以下代码中提供了一个基本的自承载服务。

Imports System
Imports System.Runtime.Serialization
Imports System.ServiceModel
Imports System.ServiceModel.Description

<ServiceContract()> _
Public Interface ISimpleService
    <OperationContract()> _
    Function SimpleMethod(ByVal msg As String) As String
End Interface

Class SimpleService
    Implements ISimpleService

    Public Function SimpleMethod(ByVal msg As String) As String Implements ISimpleService.SimpleMethod
        Console.WriteLine("The caller passed in " + msg)
        Return "Hello " + msg
    End Function
End Class
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;
        }
    }

在代码中发布元数据

  1. 在控制台应用程序的主方法中,通过传入服务类型和基址来实例化 ServiceHost 对象。

    Dim svcHost As New ServiceHost(GetType(SimpleService), New Uri("https://localhost:8001/MetadataSample"))
    
    ServiceHost svcHost = new ServiceHost(typeof(SimpleService), new Uri("https://localhost:8001/MetadataSample"));
    
  2. 紧接在步骤 1 的代码下面创建一个 try 块,这将捕获在服务运行过程中引发的任何异常。

    Try
    
    try
    {
    
    Catch commProblem As CommunicationException
    
        Console.WriteLine("There was a communication problem. " + commProblem.Message)
        Console.Read()
    End Try
    
    }
    catch (CommunicationException commProblem)
    {
        Console.WriteLine("There was a communication problem. " + commProblem.Message);
        Console.Read();
    }
    
  3. 检查服务主机是否已经包含一个 ServiceMetadataBehavior,如果没有,则创建一个新的 ServiceMetadataBehavior 实例。

    'Check to see if the service host already has a ServiceMetadataBehavior
    Dim smb As ServiceMetadataBehavior = svcHost.Description.Behaviors.Find(Of ServiceMetadataBehavior)()
    'If not, add one
    If (smb Is Nothing) Then
        smb = New ServiceMetadataBehavior()
    End If
    
    // Check to see if the service host already has a ServiceMetadataBehavior
    ServiceMetadataBehavior smb = svcHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
    // If not, add one
    if (smb == null)
        smb = new ServiceMetadataBehavior();
    
  4. HttpGetEnabled 属性设置为 true.

    smb.HttpGetEnabled = True
    
    smb.HttpGetEnabled = true;
    
  5. ServiceMetadataBehavior 包含一个 MetadataExporter 属性。MetadataExporter 包含一个 PolicyVersion 属性。将 PolicyVersion 属性的值设置为 Policy15。还可以将 PolicyVersion 属性设置为 Policy12。当设置为 Policy15 时,元数据导出程序会使用符合 WS-Policy 1.5 的元数据生成策略信息。当设置为 Policy12 时,元数据导出程序会生成符合 WS-Policy 1.2 的策略信息。

    smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15
    
    smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
    
  6. ServiceMetadataBehavior 实例添加到服务主机的行为集合。

    svcHost.Description.Behaviors.Add(smb)
    
    svcHost.Description.Behaviors.Add(smb);
    
  7. 将元数据交换终结点添加到服务主机。

    'Add MEX endpoint
    svcHost.AddServiceEndpoint( _
          ServiceMetadataBehavior.MexContractName, _
          MetadataExchangeBindings.CreateMexHttpBinding(), _
          "mex")
    
    // Add MEX endpoint
    svcHost.AddServiceEndpoint(
      ServiceMetadataBehavior.MexContractName,
      MetadataExchangeBindings.CreateMexHttpBinding(),
      "mex"
    );
    
  8. 将应用程序终结点添加到服务主机。

    'Add application endpoint
    svcHost.AddServiceEndpoint(GetType(ISimpleService), New WSHttpBinding(), "")
    
    // Add application endpoint
    svcHost.AddServiceEndpoint(typeof(ISimpleService), new WSHttpBinding(), "");
    
    Aa738489.note(zh-cn,VS.100).gif注意:
    如果不希望向服务添加任何终结点,则运行时为您添加默认终结点。在此示例中,由于服务的 ServiceMetadataBehavior 设置为 true,因此服务还启用了发布元数据。有关默认终结点的更多信息,请参见简化配置WCF 服务的简化配置

  9. 打开服务主机并等待传入调用。当用户按 Enter 时,关闭服务主机。

    'Open the service host to accept incoming calls
    svcHost.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.
    svcHost.Close()
    
    // Open the service host to accept incoming calls
    svcHost.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.
    svcHost.Close();
    
  10. 生成并运行控制台应用程序。

  11. 使用 Internet Explorer 浏览服务的基址(本示例中的 https://localhost:8001/MetadataSample)并验证是否已打开元数据发布。您应会看到一个网页,该网页顶部显示“Simple Service”(简单服务),其下面紧接着显示“You have created a service”(已经创建服务)。如果未显示上述内容,则结果页顶部会显示消息:“Metadata publishing for this service is currently disabled”(当前禁用服务的元数据发布)。

示例

下面的代码示例演示如何在代码中实现发布服务的元数据的基本 WCF 服务。

Imports System
Imports System.Runtime.Serialization
Imports System.ServiceModel
Imports System.ServiceModel.Description

<ServiceContract()> _
Public Interface ISimpleService
    <OperationContract()> _
    Function SimpleMethod(ByVal msg As String) As String
End Interface

Class SimpleService
    Implements ISimpleService

    Public Function SimpleMethod(ByVal msg As String) As String Implements ISimpleService.SimpleMethod
        Console.WriteLine("The caller passed in " + msg)
        Return "Hello " + msg
    End Function
End Class

Module Module1

    Sub Main()
        Dim svcHost As New ServiceHost(GetType(SimpleService), New Uri("https://localhost:8001/MetadataSample"))
        Try
            'Check to see if the service host already has a ServiceMetadataBehavior
            Dim smb As ServiceMetadataBehavior = svcHost.Description.Behaviors.Find(Of ServiceMetadataBehavior)()
            'If not, add one
            If (smb Is Nothing) Then
                smb = New ServiceMetadataBehavior()
            End If
            smb.HttpGetEnabled = True
            smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15
            svcHost.Description.Behaviors.Add(smb)
            'Add MEX endpoint
            svcHost.AddServiceEndpoint( _
                  ServiceMetadataBehavior.MexContractName, _
                  MetadataExchangeBindings.CreateMexHttpBinding(), _
                  "mex")
            'Add application endpoint
            svcHost.AddServiceEndpoint(GetType(ISimpleService), New WSHttpBinding(), "")
            'Open the service host to accept incoming calls
            svcHost.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.
            svcHost.Close()
        Catch commProblem As CommunicationException

            Console.WriteLine("There was a communication problem. " + commProblem.Message)
            Console.Read()
        End Try
    End Sub
End Module
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 svcHost = new ServiceHost(typeof(SimpleService), new Uri("https://localhost:8001/MetadataSample"));
            try
            {
                // Check to see if the service host already has a ServiceMetadataBehavior
                ServiceMetadataBehavior smb = svcHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
                // If not, add one
                if (smb == null)
                    smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                svcHost.Description.Behaviors.Add(smb);
                // Add MEX endpoint
                svcHost.AddServiceEndpoint(
                  ServiceMetadataBehavior.MexContractName,
                  MetadataExchangeBindings.CreateMexHttpBinding(),
                  "mex"
                );
                // Add application endpoint
                svcHost.AddServiceEndpoint(typeof(ISimpleService), new WSHttpBinding(), "");
                // Open the service host to accept incoming calls
                svcHost.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.
                svcHost.Close();
            }
            catch (CommunicationException commProblem)
            {
                Console.WriteLine("There was a communication problem. " + commProblem.Message);
                Console.Read();
            }
        }
    }
}

另请参见

任务

如何:在托管应用程序中承载 WCF 服务
自承载
如何:使用配置文件发布服务的元数据

概念

元数据体系结构概述
使用元数据