«Подходит несколько фильтров». при использовании одного и того же адреса для нескольких конечных точек в WCF - PullRequest
3 голосов
/ 12 декабря 2011

Итак, из-за некоторых организационных проблем я разделил то, что изначально было единым интерфейсным контрактом, на два отдельных.Теперь у меня есть только один класс, реализующий оба интерфейса, и я хочу сделать их доступными как REST-сервисы через WCF.Контракты перечислены ниже:

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 здесь), я вижу, что получаю следующую ошибку:

Сообщение: найдено несколько фильтров.

Stack Trace:

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)

Понятия не имею, как это решить.Насколько я могу видеть из следующих руководств, это правильный способ использовать один и тот же тип для нескольких конечных точек.Есть идеи?

Ответы [ 2 ]

0 голосов
/ 12 декабря 2011

Короткий ответ здесь заключается в том, что вам нужно запомнить азбуку Индиго ... гм ... WCF: адрес, связывание, контракт.

Тот факт, что конечные точки вашей службы реализованы в одном и том же физическом классе, не имеет отношения к абонентам вашей службы: для внешнего мира ваша служба теперь доступна через две различные конечные точки службы: IPlanning & INotification.

Измените конечные точки вашего файла 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 Friendly - webHttpBinding уже поддерживает httpGet по умолчанию. :)

Кроме того, я настоятельно рекомендую вам включить метаданные службы (особенно в процессе разработки), поскольку это позволяет вам использовать инструменты для создания прокси-классов на стороне клиента, чтобы вы могли быстро создавать (правильно настраивать) клиентские приложения и тесты.

В класс app.config вашего сервиса добавьте следующее:

<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

НТН.

0 голосов
/ 12 декабря 2011

Можете ли вы использовать нижеприведенное и посмотреть, получите ли вы еще исключение:

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

У вас не может быть двух разных конечных точек, прослушивающих один и тот же адрес.Поэтому я добавил атрибут адреса, чтобы различать их.

Ваши URL-адреса могут быть следующими при размещении в IIS:

http://localhost/ApplicationVD/PlanTrip
http://localhost/ApplicationVD/PlanTripDelayed
http://localhost/ApplicationVD/PlanTripLoc
http://localhost/ApplicationVD/More/GetInfo
http://localhost/ApplicationVD/More/RegisterRID
...