作法:擷取中繼資料並實作相容性服務

服務通常不會由同一個人設計並實作。 在重視應用程式之間互通性的環境中,可以使用 Web 服務描述語言 (WSDL) 來設計或描述合約,而開發人員則必須實作符合所提供合約的服務。 您也可能想要將現有服務移轉至 Windows Communication Foundation (WCF),但是保留 Wire 格式。 此外,雙工合約還會要求呼叫端也必須實作回呼合約。

在這些情況下,就必須使用 ServiceModel Metadata Utility Tool (Svcutil.exe) (或對等的工具) 產生使用受控語言的服務合約介面,方便您進行實作來滿足合約的需求。 通常會使用 ServiceModel Metadata Utility Tool (Svcutil.exe) 來取得與通道處理站或 WCF 用戶端類型以及用戶端組態檔 (用來設定正確的繫結和位址) 搭配使用的服務合約。 若要使用產生的組態檔,您必須將它變更為服務組態檔。 您可能還需要修改服務合約。

若要擷取資料並實作相容服務

  1. 使用 ServiceModel Metadata Utility Tool (Svcutil.exe),依據中繼資料檔案或中繼資料端點產生程式碼檔案。

  2. 搜尋輸出程式碼檔案中包含標示有 System.ServiceModel.ServiceContractAttribute 屬性之所需介面 (如果有一個以上) 的部分。 下列程式碼範例顯示由 ServiceModel Metadata Utility Tool (Svcutil.exe) 產生的兩個介面。 第一個 (ISampleService) 是您為了建立相容服務而實作的服務合約介面。 第二個 (ISampleServiceChannel) 是供用戶端使用的 Helper 介面,這個介面會擴充服務合約介面及 System.ServiceModel.IClientChannel,而且可以在用戶端應用程式中使用。

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(
      Namespace="http://microsoft.wcf.documentation"
    )]
    public interface ISampleService
    {
    
        [System.ServiceModel.OperationContractAttribute(
          Action="http://microsoft.wcf.documentation/ISampleService/SampleMethod",
          ReplyAction="http://microsoft.wcf.documentation/ISampleService/SampleMethodResponse"
        )]
        [System.ServiceModel.FaultContractAttribute(
          typeof(microsoft.wcf.documentation.SampleFault),
          Action="http://microsoft.wcf.documentation/ISampleService/SampleMethodSampleFaultFault"
        )]
        string SampleMethod(string msg);
    }
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    public interface ISampleServiceChannel : ISampleService, System.ServiceModel.IClientChannel
    {
    }
    
  3. 如果 WSDL 沒有為所有的作業指定回覆動作,則產生的作業合約可能會將 ReplyAction 屬性設定為萬用字元 (*)。 請移除這個屬性設定。 否則,當您實作服務合約中繼資料時,就無法匯出這些作業的中繼資料。

  4. 在類別上實作介面並裝載服務。 例如,請參閱操作說明:實作服務合約,或參閱以下<範例>一節中的簡單實作。

  5. ServiceModel Metadata Utility Tool (Svcutil.exe) 產生的用戶端組態檔中,將 <client> 組態區段變更為 <services> 組態區段。 (如需所產生之用戶端應用程式組態檔的範例,請參閱下列<範例>一節)。

  6. <services> 組態區段中,為您的服務實作在 <services> 組態區段中建立 name 屬性。

  7. 將服務的 name 屬性設定為服務實作的組態名稱。

  8. 將使用實作服務合約的端點組態項目加入至服務組態區段。

範例

下列程式碼範例顯示依據中繼資料檔案執行 ServiceModel Metadata Utility Tool (Svcutil.exe) 所產生的程式碼檔案之主要部分。

下列程式碼顯示:

  • 服務合約介面,這個介面會在實作之後符合合約需求 (ISampleService)。

  • 供用戶端使用的 Helper 介面,這個介面會擴充服務合約介面及 System.ServiceModel.IClientChannel,而且可以在用戶端應用程式中 (ISampleServiceChannel) 使用。

  • Helper 類別,這個類別會擴充 System.ServiceModel.ClientBase<TChannel>,而且可以在用戶端應用程式 (SampleServiceClient) 中使用。

  • 從服務產生的組態檔。

  • 簡易 ISampleService 服務實作。

  • 用戶端組態檔轉換為服務端版。

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:2.0.50727.42
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

[assembly: System.Runtime.Serialization.ContractNamespaceAttribute("http://microsoft.wcf.documentation", ClrNamespace="microsoft.wcf.documentation")]

namespace microsoft.wcf.documentation
{
    using System.Runtime.Serialization;

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
    [System.Runtime.Serialization.DataContractAttribute()]
    public partial class SampleFault : object, System.Runtime.Serialization.IExtensibleDataObject
    {

        private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

        private string FaultMessageField;

        public System.Runtime.Serialization.ExtensionDataObject ExtensionData
        {
            get
            {
                return this.extensionDataField;
            }
            set
            {
                this.extensionDataField = value;
            }
        }

        [System.Runtime.Serialization.DataMemberAttribute()]
        public string FaultMessage
        {
            get
            {
                return this.FaultMessageField;
            }
            set
            {
                this.FaultMessageField = value;
            }
        }
    }
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(
  Namespace="http://microsoft.wcf.documentation"
)]
public interface ISampleService
{

    [System.ServiceModel.OperationContractAttribute(
      Action="http://microsoft.wcf.documentation/ISampleService/SampleMethod",
      ReplyAction="http://microsoft.wcf.documentation/ISampleService/SampleMethodResponse"
    )]
    [System.ServiceModel.FaultContractAttribute(
      typeof(microsoft.wcf.documentation.SampleFault),
      Action="http://microsoft.wcf.documentation/ISampleService/SampleMethodSampleFaultFault"
    )]
    string SampleMethod(string msg);
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface ISampleServiceChannel : ISampleService, System.ServiceModel.IClientChannel
{
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class SampleServiceClient : System.ServiceModel.ClientBase<ISampleService>, ISampleService
{

    public SampleServiceClient()
    {
    }

    public SampleServiceClient(string endpointConfigurationName) :
            base(endpointConfigurationName)
    {
    }

    public SampleServiceClient(string endpointConfigurationName, string remoteAddress) :
            base(endpointConfigurationName, remoteAddress)
    {
    }

    public SampleServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
            base(endpointConfigurationName, remoteAddress)
    {
    }

    public SampleServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
            base(binding, remoteAddress)
    {
    }

    public string SampleMethod(string msg)
    {
        return base.Channel.SampleMethod(msg);
    }
}
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_ISampleService" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                    useDefaultWebProxy="true">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <security mode="None">
                        <transport clientCredentialType="None" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="UserName" algorithmSuite="Default" />
                    </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8080/SampleService" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_ISampleService" contract="ISampleService"
                name="BasicHttpBinding_ISampleService" />
        </client>
    </system.serviceModel>
</configuration>
// Implement the service. This is a very simple service.
class SampleService : ISampleService
{
  public string SampleMethod(string msg)
  {
    Console.WriteLine("The caller said: \"{0}\"", msg);
    return "The service greets you: " + msg;
  }
}
<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_ISampleService" closeTimeout="00:01:00"
            openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
            allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
            maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
            messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
            useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <services>
      <service
          name="Microsoft.WCF.Documentation.SampleService">
        <endpoint address="http://localhost:8080/SampleService" binding="basicHttpBinding"
            bindingConfiguration="BasicHttpBinding_ISampleService" contract="Microsoft.WCF.Documentation.ISampleService"
            />
      </service>
    </services>
  </system.serviceModel>
</configuration>

另請參閱