2011-05-12 2 views
1

wcf를 사용하여 서비스를 작성하고 있습니다. 나는이 개 프로젝트 솔루션을 만들었습니다WCF에서 서비스 주소를 지정하는 중 문제가 발생했습니다.

  • 도서관 : 프로젝트는 (인터페이스를 포함하고 해당 서비스에 대한 해당 구현) 서비스와 관련된 파일을 저장합니다. 이 프로젝트는 도서관 프로젝트입니다.
  • 호스팅 응용 프로그램 이러한 서비스를 호스팅하기위한 프로젝트입니다 (자체 호스팅). 이런 이유로이 프로젝트는 서비스를 구성하기 위해 필요한 정보를 저장하는 config 파일을 가지고있는 실행 가능한 프로젝트입니다.

서비스를 호출하기 위해 클라이언트도 작성했습니다. 이를 클라이언트 응용 프로그램이라고합니다.

나는 서비스를 제공합니다.

namespace EchoWcfLibrary { 
    /// <summary> 
    /// The interface specifies for those classes implementing it (services), the operation that the service will expose. 
    /// </summary> 
    [ServiceContract] 
    public interface IService1 { 
     // This does not use serialization (implicit serialization in considered: base types used). 
     [OperationContract] 
     string GetData(int value); 
     // This uses data contracts and serialization. 
     [OperationContract] 
     CompositeType GetDataUsingDataContract(CompositeType composite); 
    } 

    [DataContract] 
    public class CompositeType { 
     // Members not serialized 
     bool boolValue = true; 
     string stringValue = "Hello "; 
     // Serialized 
     [DataMember] 
     public bool BoolValue { 
      get { return boolValue; } 
      set { boolValue = value; } 
     } 
     // Serialized 
     [DataMember] 
     public string StringValue { 
      get { return stringValue; } 
      set { stringValue = value; } 
     } 
    } 
} 

다음은 서비스 호스트 응용 프로그램의 시작 (실행 가능한 프로젝트)입니다 :

namespace WcfServiceApplication { 
    public static class Program { 
     static void Main(string[] args) { 
      // Setting endpoints and setting the service to start properly. 
      // Base address specified: http://localhost:8081/Service1 
      Console.WriteLine("Beginning..."); 
      using (ServiceHost host = new ServiceHost(typeof(Service1), new Uri("http://localhost:8081/Service1"))) { 
       Console.WriteLine("Opening host..."); 
       host.Open(); 
       Console.WriteLine("Waiting..."); 
       System.Threading.Thread.Sleep(1000000); 
       Console.WriteLine("Closing..."); 
       host.Close(); 
       Console.WriteLine("Quitting..."); 
      } 
     } 
    } 
} 

다음은 실행 가능한 프로젝트의 App.config (인 인터페이스와 구현 (라이브러리 프로젝트는) 다음 호스팅 응용 프로그램) :

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 

    <!-- When deploying the service library project, the content of the config file must be added to the host's 
    app.config file. System.Configuration does not support config files for libraries. --> 
    <system.serviceModel> 
     <services> 
      <service name="WcfServiceLibrary.Service1"> 
       <host> 
        <baseAddresses> 
         <add baseAddress="http://localhost:8081/Service1" /> 
        </baseAddresses> 
       </host> 
       <!-- Service Endpoints --> 
       <!-- Unless fully qualified, address is relative to base address supplied above --> 
       <endpoint address="/GoInto/Svc" 
            binding="basicHttpBinding" 
            contract="WcfServiceLibrary.IService1"> 
        <!-- 
       Upon deployment, the following identity element should be removed or replaced to reflect the 
       identity under which the deployed service runs. If removed, WCF will infer an appropriate identity 
       automatically. 
      --> 
        <identity> 
         <dns value="localhost"/> 
        </identity> 
       </endpoint> 
       <endpoint address="/GoInto/Sav" 
            binding="basicHttpBinding" 
            contract="WcfServiceLibrary.IService1"> 
        <!-- 
       Upon deployment, the following identity element should be removed or replaced to reflect the 
       identity under which the deployed service runs. If removed, WCF will infer an appropriate identity 
       automatically. 
      --> 
        <identity> 
         <dns value="localhost"/> 
        </identity> 
       </endpoint> 
       <!-- Metadata Endpoints --> 
       <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. --> 
       <!-- This endpoint does not use a secure binding and should be secured or removed before deployment --> 
       <endpoint address="GoInto/Mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 
      </service> 
     </services> 

     <behaviors> 
      <serviceBehaviors> 
       <behavior> 
        <!-- To avoid disclosing metadata information, 
      set the value below to false and remove the metadata endpoint above before deployment --> 
        <serviceMetadata httpGetEnabled="True"/> 
        <!-- To receive exception details in faults for debugging purposes, 
      set the value below to true. Set to false before deployment 
      to avoid disclosing exception information --> 
        <serviceDebug includeExceptionDetailInFaults="False" /> 
       </behavior> 
      </serviceBehaviors> 
     </behaviors> 
    </system.serviceModel> 

</configuration> 

다음은 클라이언트 실행 프로젝트의 프로그램 시작 (라이브러리 프로젝트에 대한 링크가 만들어 짐), basica lly 클라이언트입니다.

namespace WcfServiceClient { 
    class Program { 
     static void Main(string[] args) { 
      ServiceEndpoint httpEndpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IService1)), new BasicHttpBinding(), new EndpointAddress("http://localhost:8081/Service1")); 
      ChannelFactory<IService1> channelFactory = new ChannelFactory<IService1>(httpEndpoint); 
      IService1 svc = channelFactory.CreateChannel(); 
      Console.WriteLine(svc.GetData(121)); 
      System.Threading.Thread.Sleep(10000); 
     } 
    } 
} 

음 ... 내 문제는 다음과 같습니다.이 응용 프로그램은 작동합니다. 왜 문제입니까 ??? 문제는 서비스를 호스팅 할 때 App.config 파일에 세 개의 끝점 : 두 개의 basicHttp 및 한 개의 메타 데이터 끝점을 지정했기 때문입니다. 자, <endpoint address="/GoInto/Svc"... 엔드 포인트에 대해 말씀 드리고 싶습니다.이 주소 (기본 주소를 지정했음을 유의하십시오)는 http://localhost:8081/Service1/GoInto/Svc입니다.

글쎄, 불행하게도 클라이언트에서이 엔드 포인트를 주소로 지정합니다 : http://localhost:8081/Service1 그냥 기본 주소입니다 ...... 왜 작동합니까 ???? 나는 클라이언트에서이 주소를 지정하려면 :

namespace WcfServiceClient { 
    class Program { 
     static void Main(string[] args) { 
      ServiceEndpoint httpEndpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IService1)), new BasicHttpBinding(), new EndpointAddress("http://localhost:8081/Service1/GoInto/Svc")); 
      ChannelFactory<IService1> channelFactory = new ChannelFactory<IService1>(httpEndpoint); 
      IService1 svc = channelFactory.CreateChannel(); 
      Console.WriteLine(svc.GetData(121)); 
      System.Threading.Thread.Sleep(10000); 
     } 
    } 
} 

을하지만이 작업을 수행 할 경우, 불일치 오류가 발생합니다 :

으로 'HTTP와 메시지 : // localhost를 : 8081/서비스 1을/GoInto/Svc ' EndofDispatcher에서 AddressFilter가 일치하지 않아 수신기에서 을 처리 할 수 ​​없습니다. 보낸 사람과받는 사람의 끝점 주소가 일치하는지 확인합니다.

왜 작동하지 않습니까?

답변

1

기본 주소는 ServiceHost 생성자 또는 요소에서 한 곳에서 지정해야합니다. 두 곳 모두에있는 경우 WCF는 동일한 구성표 (HTTP)에 대해 두 개의 기본 주소가 있다는 예외를 throw합니다.

호스팅 프로젝트의 app.config에있는 서비스 이름이 일치하지 않아서 구성을 선택하지 못했을 가능성이 있습니다 (기본 엔드 포인트는 주소가 기본 주소와 동일한 주소). 호스팅 코드에 foreach 루프를 추가하면 서비스가 수신 대기중인 엔드 포인트의 주소가 표시됩니다.

   Console.WriteLine("Opening host..."); 
      host.Open(); 

      foreach (ServiceEndpoint endpoint in host.Description.Endpoints) 
      { 
       Console.WriteLine("Endpoint:"); 
       Console.WriteLine(" Address: {0}", endpoint.Address.Uri); 
       Console.WriteLine(" Binding: {0}", endpoint.Binding); 
       Console.WriteLine(" Contract: {0}", endpoint.Contract.Name); 
      } 

      Console.WriteLine("Waiting..."); 
관련 문제