Служба, размещенная в WCF IIS, несколько контрактов на обслуживание, реализованных одной службой - как поделиться uri между конечными точками через конфигурацию

У меня есть набор контрактов на обслуживание, которые разделяют мой интерфейс службы на части связанных функций. В настоящее время я реализую все контракты с использованием одного класса обслуживания (возможно, позже я захочу разделить их, но пока достаточно одного класса обслуживания).

Я пытаюсь настроить конечные точки с помощью файла конфигурации (в отличие от кода). Проблема в том, что я получаю ServiceActivationException, потому что две конечные точки (по одной для каждого контракта службы) пытаются прослушивать один и тот же uri. Детали исключения говорят, что для достижения этого две конечные точки должны совместно использовать объект привязки, что имеет смысл, но я не могу понять, как это сделать с помощью конфигурации (я не пробовал делать это с помощью кода, поскольку я размещаю в IIS, но Я могу представить, что это простое упражнение для настройки в коде).

Ниже приводится конфигурация, которую я использую в настоящее время (это все еще разработка, поэтому я не беспокоюсь о проблемах безопасности и т. Д., Которые могут быть обнаружены некоторыми из этих настроек):

<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
  <service name="CDC.WebPortal.MidTier.MidTierAccessService"
           behaviorConfiguration="MidTierServiceBehaviour" >
    <endpoint address=""
              binding="webHttpBinding"
              bindingConfiguration="RestBindingConfiguration"
              contract="****************************.IProductService" />

    <endpoint address=""
              binding="webHttpBinding"
              bindingConfiguration="RestBindingConfiguration"
              contract="****************************.ICategoryService" />

    <endpoint address="mex" binding="mexHttpBinding"
              contract="IMetadataExchange" />

  </service>
</services>

<bindings>
  <webHttpBinding>
    <binding name="RestBindingConfiguration"
             maxReceivedMessageSize="104857600">
      <readerQuotas maxStringContentLength="104857600"/>
    </binding>
  </webHttpBinding>
</bindings>

<behaviors>
  <serviceBehaviors>
    <behavior name="MidTierServiceBehaviour">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>
  </serviceBehaviors>
</behaviors>

So my question is how do I share this binding between the two endpoints?

Комментарии в этом вопросе SO предполагают, что я, возможно, не смогу это сделать, но я не верьте, что это правильно.

ОБНОВЛЕНИЕ 1 Согласно этой публикации MS то, что я делаю, должно быть в порядке ...

ОБНОВЛЕНИЕ 2 Вот содержание файла SVC, если это помогает:

<%@ ServiceHost Language="VB" Debug="true"
                Service="*********************.MidTierAccessService"
                Factory="Microsoft.ServiceModel.Web.WebServiceHost2Factory" %>

ОБНОВЛЕНИЕ 3. Подробная информация об исключении:

Экземпляр привязки уже был связан для прослушивания URI '********************'. Если две конечные точки хотят использовать один и тот же ListenUri, они также должны совместно использовать один и тот же экземпляр объекта привязки. Две конфликтующие конечные точки были либо указаны в вызовах AddServiceEndpoint (), в файле конфигурации, либо в сочетании AddServiceEndpoint () и config.

ОБНОВЛЕНИЕ 4 Хорошо, я пропустил это ранее, заявив: «Вам нужно будет использовать относительные адреса при открытии более одной конечной точки для конкретной службы .svc». Причина этого в том, что виртуальный каталог IIS определяет базовый адрес службы. Может ли кто-нибудь объяснить это более подробно, например, почему IIS требуется относительная адресация для каждого контракта.


person Simon Fox    schedule 25.09.2009    source источник


Ответы (1)


Насколько мне известно, и я много работал с WCF в последний месяц, вы не можете использовать один и тот же точный URI для более чем одной конечной точки. В WCF «служба» определяется не реализацией контракта, а самим контрактом (который также следует WSDL и стандартным практикам SOA). Конечные точки позволяют вам предоставлять одну службу через несколько протоколов (и, следовательно, разные адреса) , но вы не можете использовать разные службы по одному и тому же адресу. По логике, это не сработает.

Предположим следующий сценарий (это то, что вы пытаетесь выполнить):

IProductService exposed @ http://localhost/service
ICategoryService exposed @ http://localhost/service
IMetadataExchange exposed @ http://localhost/service/mex

Получить доступ к конечной точке MEX достаточно просто ... она имеет уникальный URI. Однако как получить доступ к IProductService или ICategoryService? Нет ничего, что позволяло бы различать их, кроме URI. В WCF нет ничего, что позволило бы ему маршрутизировать сообщения, которые должны отправляться в IProductservice, и сообщениями, которые должны отправляться в ICategoryService. Поскольку оба используют один и тот же URI, у вас действительно есть конфликт. Каждый КОНТРАКТ службы должен быть представлен через уникальный URI. Каждая конечная точка, использующая одну и ту же точную привязку, должна использовать отдельный адрес.

Есть способ добиться того, что вам нужно. Проблема в маршрутизации сообщений. WCF изначально не поддерживает маршрутизацию сообщений OOB, однако дает возможность реализовать собственный маршрутизатор сообщений. (Или, если вы хотите использовать бета-версию, .NET 4.0 поставляется с маршрутизатором сообщений из коробки, основываясь на статьях, ссылки на которые приведены ниже, но с улучшенными возможностями настройки.) Мишель Бустаманте, настоящая волшебница WCF, предоставила Полная реализация и статья с описанием маршрутизации сообщений по следующим ссылкам:

http://msdn.microsoft.com/en-us/magazine/cc500646.aspx http://msdn.microsoft.com/en-us/magazine/cc546553.aspx

Общая идея состоит в том, что вы настраиваете одну службу, которая прослушивает один URI. Эта служба использует отправку с подстановочными знаками для одной операции службы, которая затем определяет, на какой уникальный URI направлять каждое сообщение. Вы можете сделать определение любым удобным для вас способом, однако самый простой - это запрос Action, предполагающий, что каждое действие на ваших двух интерфейсах, IProductService и ICategoryService, глобально уникально. Однако в конечном итоге у вас будет больше сервисов ... сам маршрутизатор - это отдельная служба WCF, которую необходимо размещать так же, как и любую другую.

person jrista    schedule 25.09.2009