WCF IIS hosted service несколько сервисных контрактов, реализованных одной службой - как я могу поделиться uri между конечными точками через config


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

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

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

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

Итак мой вопрос заключается в том, как разделить эту привязку между двумя конечными точками?

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

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

UPDATE2 вот содержимое файла svc, если это поможет:

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

UPDATE 3 Вот деталь исключения:

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

UPDATE 4 Ok я пропустил это раньше, заявив: "вам нужно будет использовать относительные адреса при предоставлении более одной конечной точки для определенный.служба svc". Причина этого - что-то связанное с виртуальным каталогом IIS, определяющим базовый адрес службы, может ли кто-нибудь объяснить это немного более подробно, т. е. почему IIS нуждается в относительной адресации для каждого контракта.

1 9

1 ответ:

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

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

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

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

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

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

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