2011-12-12 2 views
3

그래서 조직적인 문제로 인해 단일 인터페이스 계약을 처음으로 두 개의 분리 된 계약으로 분리했습니다. 이제는 두 인터페이스를 모두 구현하는 클래스가 하나 뿐이므로이를 WCF를 통해 REST 서비스로 모두 사용할 수있게하려고합니다. 계약은 다음과 같습니다 :"여러 필터가 일치했습니다."

1 :

[ServiceContract] 
public interface INotification 
{ 
    [OperationContract] 
    [WebGet] 
    XElement GetInfo(string appID); 
    [OperationContract] 
    [WebGet] 
    void RegisterRID(string appID, string registrationID); 
} 

2 :

[ServiceContract] 
public interface IPlanning 
{ 
    [OperationContract] 
    [WebGet] 
    XElement PlanTrip(string toDestination, string fromDestination, int year, int month, int day, int hour, int minute, string appID); 
    [OperationContract] 
    [WebGet] 
    XElement PlanTripDelayed(string toDestination, string fromDestination, int year, int month, int day, int hour, int minute, string appID); 
    [OperationContract] 
    [WebGet] 
    XElement PlanTripLoc(string toDestination, string fromLat, string fromLong, int year, int month, int day, int hour, int minute, string appID); 
} 

내의 app.config는 다음과 같습니다

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
<system.serviceModel> 
    <behaviors> 
    <endpointBehaviors> 
     <behavior name="RESTFriendly"> 
     <webHttp /> 
     </behavior> 
    </endpointBehaviors> 
    </behaviors> 
    <services> 
     <service name="TravelPlannerWebService.Domain.Entity.ETravelPlanner"> 
      <endpoint binding="webHttpBinding" bindingConfiguration="" contract="TravelPlannerWebService.Acquaintance.IPlanning" behaviorConfiguration="RESTFriendly" /> 
      <endpoint binding="webHttpBinding" bindingConfiguration="" contract="TravelPlannerWebService.Acquaintance.INotification" behaviorConfiguration="RESTFriendly" /> 
      <host> 
       <baseAddresses> 
        <add baseAddress="http://localhost:80" /> 
       </baseAddresses> 
      </host> 
     </service> 
    </services> 
</system.serviceModel> 

문제는, 두 개의 인터페이스를 사용할 때마다 오류가 발생합니다. 내 app_tracelog.svclog (app.config에서 의도적으로 여기에서 디버그 코드를 제거함)를 살펴보면 다음 오류가 발생합니다.

메시지 : 여러 개의 필터가 일치했습니다.

스택 추적 :

System.ServiceModel.Dispatcher.EndpointDispatcherTable.LookupInCache(Message message, Boolean&amp; addressMatched) 
System.ServiceModel.Dispatcher.EndpointDispatcherTable.Lookup(Message message, Boolean&amp; addressMatched) 
System.ServiceModel.Dispatcher.ChannelHandler.GetDatagramChannel(Message message, EndpointDispatcher&amp; endpoint, Boolean&amp; addressMatched) 
System.ServiceModel.Dispatcher.ChannelHandler.EnsureChannelAndEndpoint(RequestContext request) 
      System.ServiceModel.Dispatcher.ChannelHandler.TryRetrievingInstanceContext(RequestContext request) 
System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext) 
System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result) 
System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result) 
System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) 
System.Runtime.AsyncResult.Complete(Boolean completedSynchronously) 
System.Runtime.InputQueue`1.AsyncQueueReader.Set(Item item) 
System.Runtime.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread) 
System.Runtime.InputQueue`1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread) 
System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, Action dequeuedCallback, Boolean canDispatchOnThisThread) 
System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, Action callback) 
System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult result) 
System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result) 
System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) 
System.Net.LazyAsyncResult.Complete(IntPtr userToken) 
System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken) 
System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) 
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP) 

나는이 문제를 해결하는 방법을 모른다. 내가 알 수있는 한, 다음 가이드에서, 이것은 여러 엔드 포인트에 대해 동일한 유형을 사용하는 올바른 방법입니다. 어떤 아이디어?

답변

0

당신은 아래 사용하고 당신은 여전히 ​​예외 얻는 경우에 볼 수 있습니다

<service name="TravelPlannerWebService.Domain.Entity.ETravelPlanner"> 
     <endpoint address="" binding="webHttpBinding" bindingConfiguration="" contract="TravelPlannerWebService.Acquaintance.IPlanning" behaviorConfiguration="RESTFriendly" /> 
     <endpoint address="more" binding="webHttpBinding" bindingConfiguration="" contract="TravelPlannerWebService.Acquaintance.INotification" behaviorConfiguration="RESTFriendly" /> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://localhost:80" /> 
      </baseAddresses> 
     </host> 
     </service> 

당신은 동일한 주소에서 수신이 다른 엔드 포인트를 가질 수 있습니다. 따라서 주소 속성을 구분하기 위해 추가했습니다. IIS에서 호스팅 할 때 다음과 같이

귀하의 URL이 될 수 있습니다 바인딩 주소 :

http://localhost/ApplicationVD/PlanTrip 
http://localhost/ApplicationVD/PlanTripDelayed 
http://localhost/ApplicationVD/PlanTripLoc 
http://localhost/ApplicationVD/More/GetInfo 
http://localhost/ApplicationVD/More/RegisterRID 
+0

http://msdn.microsoft.com/en-us/library/aa395210.aspx의 예에서 서로 다른 계약이있는 두 개의 끝점에 대해 동일한 주소를 사용하기 때문에 이상합니다. –

+0

아티클을 보면 값이 설정된 ListenUri 속성을 사용하고 있으며 해당 속성을 사용하면 동일한 주소에서 수신하는 다른 계약서를 사용할 수 있습니다. – Rajesh

+0

좋아요, ListenUri가 둘 다 동일한 값을 갖고 있기 때문에 필요하지 않다고 생각했습니다. 그 접근법을 시도 할 것입니다. –

0

여기에 짧은 대답은 당신이 에헴 의 ABC 인디고 ... WCF를 기억할 필요가있다 , 계약.

서비스의 끝점이 동일한 실제 클래스 내에서 구현된다는 사실은 서비스 호출자와 관련이 없습니다. 외부 세계에 서비스는 이제 두 개의 별개 서비스 끝점 인 IPlanning & 내선을 통해 노출됩니다.

(서비스의 기본 주소를 기준으로) 자신의 주소에서 각 서비스 엔드 포인트에 노출하기 위해 app.config 파일의 엔드 포인트를 수정

<endpoint name ="TripPlanningEndpoint" 
    address="Planning" binding="webHttpBinding" contract="Service.IPlanning" 
    behaviorConfiguration="RESTFriendly" /> 

<endpoint name="TripNotificationsEndpoint" 
    address="Notifications" binding="webHttpBinding" contract="Service.INotification" 
    behaviorConfiguration="RESTFriendly" /> 

아 ... 그리고 당신은 모든 REST 동반이 필요하지 않습니다 끝점 동작 stuff - webHttpBinding은 기본적으로 httpGet을 이미 지원합니다. :)

또한 서비스 메타 데이터 (esp '개발 중)를 사용하도록 설정하는 것이 좋습니다. 도구를 사용하여 클라이언트 측 프록시 클래스를 생성 할 수 있으므로 클라이언트 응용 프로그램을 빠르게 빌드하고 테스트.

귀하의 서비스 앱입니다.

<system.serviceModel> 
    <behaviors> 
    ... 
     <serviceBehaviors> 
      <behavior name="ServiceMetadataBehavior"> 
       <serviceMetadata httpGetEnabled="true"/> 
      </behavior> 
     </serviceBehaviors> 
    </behaviors> 

또한 서비스의 메타 데이터를 노출하는 별도의 엔드 포인트를 추가 : 설정 클래스는 다음을 추가

이제 "서비스 참조 추가"를 사용하여 클라이언트/테스트 응용 프로그램에 대한 참조를 추가 할 수 있습니다
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" /> 

: Multi-interface WCF Service - Add Reference Dialog

HTH.

+0

http://msdn.microsoft.com/en-us/library/aa395210.aspx에서 실제로 동일한 주소를 공유하는 별도의 계약으로 두 개의 끝점을 가질 수 있음을 보여줍니다. 내가 실수 한거야? 모든 메소드의 테스트가 하나의 인터페이스 만 사용하여 이전 구현에서 이미 수행되었으므로 일부러 서비스 메타 데이터를 제거했습니다. 리팩토링은 아키텍처와 관련하여 수행되었습니다 (더 나은 개요 제공). –