Как настроить службу WCF с двумя конечными точками для использования разных ListenUri для каждой конечной точки?

У меня есть служба WCF, которая предоставляет конечную точку с помощью webHttpBinding и используется как приложениями WPF, так и ASP.NET. Все отлично работает.

Сейчас я пытаюсь использовать сервис из Windows Phone (WP7). Однако, поскольку .NET Framework еще не догнала WP7, пространство имен System.ServiceModel.Web недоступно, в результате чего webHttpBinding не работает в WP7.

Теперь, в моем сервисе, если я переключаю webHttpBinding на basicHttpBinding, телефонное приложение работает.

Однако я не хочу переделывать свои приложения WPF и ASP.NET, чтобы использовать basicHttpBinding.

Я понимаю, что WCF может поддерживать несколько привязок, и я попытался настроить и запустить службу, чтобы она предоставляла конечные точки как для webHttpBinding, так и для basicHttpBinding. Служба запускается нормально. Однако приложения WPF и ASP.NET не могут получить к нему доступ. И когда я пытаюсь создать ссылку на службу в приложении WP7, я получаю следующее сообщение:

Экземпляр привязки уже связан для прослушивания URI «http://localhost:1726/GeneralService.svc». Если две конечные точки хотят использовать один и тот же ListenUri, они также должны использовать один и тот же экземпляр объекта привязки. Две конфликтующие конечные точки были указаны либо в вызовах AddServiceEndpoint(), либо в файле конфигурации, либо в комбинации AddServiceEndpoint() и config.

Мы с коллегой безуспешно экспериментировали с различными изменениями атрибутов baseAddress, address и listenUri. Сейчас мы находимся на стадии проб и ошибок, которые не очень эффективны.

<system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <bindings>
        <basicHttpBinding>
            <binding name="generalBasic" />
        </basicHttpBinding>
        <webHttpBinding>
            <binding name="general" maxReceivedMessageSize="2147483647">
                <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" />
                <security mode="None">
                    <transport clientCredentialType="None" />
                </security>
            </binding>
        </webHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior>
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false" />
            </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="web">
                <webHttp />
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <services>
        <service name="MyProject.GeneralService">
            <endpoint address="mex" 
                binding="mexHttpBinding"
                contract="IMetadataExchange" />
            <endpoint address="" 
                binding="basicHttpBinding" 
                bindingConfiguration="generalBasic"
                contract="MyProject.Contracts.IGeneralService" />
            <endpoint behaviorConfiguration="web" 
                binding="webHttpBinding"
                bindingConfiguration="general" 
                contract="MyProject.Contracts.IGeneralService" />
            <host>
                <baseAddresses>
                    <add baseAddress="http://localhost:1726/" />
                </baseAddresses>
            </host>
        </service>
    </services>
</system.serviceModel>

person Steve Elmer    schedule 12.01.2012    source источник
comment
Просто укажите атрибут адреса со значением базовой или веб-конечной точки, чтобы отличить ее адрес. Пример: ‹endpoint behaviorConfiguration=веб-адрес=остальная привязка=webHttpBinding bindingConfiguration=общий контракт=MyProject.Contracts.IGeneralService /› должен решить вашу проблему.   -  person Rajesh    schedule 12.01.2012
comment
хм... забавно, я пробовал это раньше, но это не сработало. (возможно, я добавил установить атрибут адреса моего basicHttpBinding, а не моего webHttpBinding). на этот раз, как вы предложили, я установил атрибут адреса моего webHttpBinding, и приложение WP7 подключилось нормально. после добавления нового значения к атрибутам адреса в моих клиентских приложениях WPF и MVC все работает как часы. Опубликуйте свой комментарий в качестве ответа, и я дам его вам. Спасибо :-)   -  person Steve Elmer    schedule 12.01.2012


Ответы (4)


Просто укажите атрибут адреса со значением базовой или веб-конечной точки, чтобы отличить ее адрес. Бывший:

<endpoint behaviorConfiguration="web" address="rest" binding="webHttpBinding" bindingConfiguration="general" contract="MyProject.Contracts.IGeneralService" /> 

должен решить вашу проблему

person Rajesh    schedule 13.01.2012
comment
@CoffeeAddict Тип контента определяет, в каком формате вы отвечаете: Json или XML. Атрибут адреса предназначен для того, чтобы различать каждую конечную точку, на которой она использует привязку, и 2 конечные точки не могут иметь один и тот же адрес. - person Rajesh; 22.10.2013
comment
Означает ли это, что когда вы хотите отправить запрос, вы должны опубликовать свой запрос на адрес с .svc/web в качестве суффикса, или вы все равно можете использовать адрес .svc? - person Emil; 14.03.2014

При определении ваших конечных точек для первого вы указываете address="", а для второго у вас нет никакого значения (так что даже для этого у нас будет адрес как "")

<endpoint address="" 
            binding="basicHttpBinding" 
            bindingConfiguration="generalBasic"
            contract="MyProject.Contracts.IGeneralService" />
        <endpoint behaviorConfiguration="web" 
            binding="webHttpBinding"
            bindingConfiguration="general" 
            contract="MyProject.Contracts.IGeneralService" />

Таким образом, в этом случае, когда мы указываем адрес как пустой, он примет базовый адрес по умолчанию.

Поэтому попробуйте указать какое-то значение для любой из конечных точек. Так что у нас будут разные адреса для этих двух конечных точек.

<endpoint address="" 
            binding="basicHttpBinding" 
            bindingConfiguration="generalBasic"
            contract="MyProject.Contracts.IGeneralService" />
        <endpoint behaviorConfiguration="web" address="WP7Service" 
            binding="webHttpBinding"
            bindingConfiguration="general" 
            contract="MyProject.Contracts.IGeneralService" />

Итак, наши новые адреса конечных точек:

  1. http://локальный:1726/GeneralService.svc
  2. http://локальный:1726/GeneralService.svc/WP7Service
person Pavan Kumar Aryasomayajulu    schedule 31.08.2012
comment
Я сделал это, не указывая адрес, когда он работал для json. - person PositiveGuy; 22.10.2013
comment
но тогда да, чтобы отличить xml от конечной точки json, вам нужно чертовски вставить глупый атрибут адреса, а не просто понять это через тип контента в запросе. Таким образом, в основном, если вы не взломаете WCF, чтобы проверить тип содержимого в запросе и сделать свой собственный код при перехвате вызова, вы не сможете использовать конечные точки xml и json для REST. Или вы должны поместить /json/ в URL-адрес и указать один с адресом = json, чтобы вы могли предоставить json и xml endoints в WCF, я думаю. - person PositiveGuy; 22.10.2013

Для службы использования на WP вы должны предоставить свою службу с конечными точками Rest, Soap или OData. В приведенной ниже ссылке довольно четко описано, как выставить WCF RIA для таких целей:
Предоставление доступа к службам WCF (SOAP\WSDL)
Мне это очень помогает.

person Anatolii Gabuza    schedule 13.01.2012

Чего мне не хватало, так это protocolMapping для обеих конечных точек:

<configuration>
  <!--...-->
  <system.serviceModel>
    <!--...-->
    <protocolMapping>
      <add binding="basicHttpBinding" scheme="http" bindingConfiguration="BasicHttpBindingConfiguration"/>
      <add binding="basicHttpsBinding" scheme="https" bindingConfiguration="SecureHttpBindingConfiguration"/>
    </protocolMapping>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBindingConfiguration" />
        <binding name="SecureHttpBindingConfiguration" >
          <security mode="Transport">
            <transport clientCredentialType="None" proxyCredentialType="None"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <services>
      <service name="Namespace.ServiceName">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBindingConfiguration"
          contract="Namespace.IServiceName" />
      </service>
      <service name="Namespace.ServiceName">
        <endpoint address="" binding="basicHttpsBinding" bindingConfiguration="BasicHttpsBindingConfiguration"
          contract="Namespace.IServiceName" />
      </service>
    </services>
    <!--...-->
  </system.serviceModel>
  <!--...-->
</configuration>
person Aske B.    schedule 29.06.2018