방법: 메타데이터 검색 및 규격 서비스 구현

서비스를 디자인하는 사람과 구현하는 사람이 다른 경우가 많습니다. 상호 운용하는 애플리케이션이 중요한 환경에서는 WSDL(웹 서비스 기술 언어)로 계약을 디자인하거나 설명할 수 있으며 개발자는 제공된 계약에 따라 서비스를 구현해야 합니다. 기존 서비스를 WCF(Windows Communication Foundation)로 마이그레이션하면서 통신 형식을 유지할 수도 있습니다. 또한 이중 계약에서는 호출자가 콜백 계약도 구현해야 합니다.

이 경우 계약 요구 사항을 준수하여 구현할 수 있도록 ServiceModel Metadata 유틸리티 도구(Svcutil.exe) 또는 이와 동등한 도구를 사용하여 서비스 계약 인터페이스를 관리되는 언어로 생성해야 합니다. 일반적으로 올바른 바인딩과 주소를 설정하는 클라이언트 구성 파일을 비롯하여 채널 팩터리 또는 WCF 클라이언트 형식으로 사용되는 서비스 계약을 가져오기 위해 ServiceModel Metadata 유틸리티 도구(Svcutil.exe)를 사용합니다. 생성된 구성 파일을 사용하려면 해당 파일을 서비스 구성 파일로 변경해야 합니다. 서비스 계약을 수정해야 할 수도 있습니다.

데이터 검색 및 규격 서비스 구현

  1. 메타데이터 파일 또는 메타데이터 엔드포인트에 대해 ServiceModel Metadata 유틸리티 도구(Svcutil.exe)를 사용하여 코드 파일을 생성합니다.

  2. System.ServiceModel.ServiceContractAttribute 특성으로 표시된 필요한 인터페이스(두 개 이상 있는 경우)를 포함하는 출력 코드 파일 부분을 검색합니다. 다음 코드 예제에서는 ServiceModel Metadata 유틸리티 도구(Svcutil.exe)에 의해 생성된 두 인터페이스를 보여 줍니다. 첫 번째(ISampleService)는 규격 서비스를 만들기 위해 구현하는 서비스 계약 인터페이스입니다. 두 번째(ISampleServiceChannel)는 서비스 계약 인터페이스 및 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 유틸리티 도구(Svcutil.exe)가 생성하는 클라이언트 구성 파일에서 <client> 구성 섹션을 <services> 구성 섹션으로 변경합니다. 생성되는 클라이언트 애플리케이션 구성 파일의 예제를 보려면 다음 "예제" 단원을 참조하세요.

  6. <services> 구성 섹션 내에서 서비스 구현에 대한 <services> 구성 섹션에서 name 특성을 만듭니다.

  7. 서비스 name 특성을 서비스 구현을 위한 구성 이름으로 설정합니다.

  8. 구현된 서비스 계약을 사용하는 엔드포인트 구성 요소를 서비스 구성 섹션에 추가합니다.

예시

다음 코드 예제에서는 메타데이터 파일에 대해 ServiceModel Metadata 유틸리티 도구(Svcutil.exe)를 실행하여 생성되는 대부분의 코드 파일을 보여 줍니다.

코드 내용은 다음과 같습니다.

  • 계약 요구 사항을 준수하는 서비스 계약 인터페이스(구현된 경우)(ISampleService).

  • 서비스 계약 인터페이스와 System.ServiceModel.IClientChannel을 모두 확장하는 클라이언트와 클라이언트 애플리케이션에 사용하기 위한 도우미 인터페이스(ISampleServiceChannel)

  • 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>

참고 항목