作法:使用程式碼發行服務的中繼資料

在兩個討論如何發行 Windows Communication Foundation (WCF) 服務中繼資料的使用指南主題中,這是其中一個。 有兩種方法可以指定服務發行中繼資料的方式,分別是使用組態檔和使用程式碼。 本主題說明如何使用程式碼發行服務的中繼資料。

警告

本主題將示範以不安全的方法發行中繼資料。 任何用戶端都能從服務擷取中繼資料。 若您的服務需要以安全的方法發行中繼資料。 請參閱自訂安全中繼資料端點

如需在組態檔中發佈中繼資料的詳細資訊,請參閱如何:使用組態檔發佈服務的中繼資料。 發行中繼資料可讓用戶端透過 WS-Transfer GET 要求,或是透過使用 ?wsdl 查詢字串的 HTTP/GET 要求來擷取中繼資料。 若要確定程式碼可以運作,您必須建立基本的 WCF 服務。 下列程式碼提供您基本的自我裝載服務。

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;
        }
    }
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

若要透過程式碼發行中繼資料

  1. 在主控台應用程式的 main 方法中,傳入服務類型與基底位址來產生 ServiceHost 物件。

    ServiceHost svcHost = new ServiceHost(typeof(SimpleService), new Uri("http://localhost:8001/MetadataSample"));
    
    Dim svcHost As New ServiceHost(GetType(SimpleService), New Uri("http://localhost:8001/MetadataSample"))
    
  2. 在步驟 1 的程式碼底下,立即建立 try 區塊,以便在執行服務時,攔截任何擲回的例外狀況。

    try
    {
    
    Try
    
    }
    catch (CommunicationException commProblem)
    {
        Console.WriteLine("There was a communication problem. " + commProblem.Message);
        Console.Read();
    }
    
    Catch commProblem As CommunicationException
    
        Console.WriteLine("There was a communication problem. " + commProblem.Message)
        Console.Read()
    End Try
    
  3. 檢查服務主機是否已包含 ServiceMetadataBehavior,如果沒有的話,建立新的 ServiceMetadataBehavior 執行個體。

    // 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();
    
    '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
    
  4. HttpGetEnabled 屬性設定為 true.

    smb.HttpGetEnabled = true;
    
    smb.HttpGetEnabled = True
    
  5. ServiceMetadataBehavior 會包含 MetadataExporter 屬性。 MetadataExporter 會包含 PolicyVersion 屬性。 將 PolicyVersion 屬性值設定為 Policy15PolicyVersion 屬性也可以設為 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(typeof(ISimpleService), new WSHttpBinding(), "");
    
    'Add application endpoint
    svcHost.AddServiceEndpoint(GetType(ISimpleService), New WSHttpBinding(), "")
    

    注意

    如果您沒有將任何端點加入至服務中,執行階段會為您加入預設端點。 在這個範例中,由於服務將 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. 瀏覽至服務的基底位址 (此範例中為 http://localhost:8001/MetadataSample),然後確認已開啟中繼資料發行功能。 您應該會看到頁面上方標示「簡易服務」,且在其下跟著「您已建立服務」的網頁。如果沒有的話,結果頁面上方應該會顯示:「為此服務發行的中繼資料目前停用」。

範例

下列程式碼範例說明可透過程式碼發行服務中繼資料的基本 WCF 服務實作。

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("http://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();
            }
        }
    }
}
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("http://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

另請參閱