How do you configure a WCF service with two endpoints to use a different ListenUri for each endpoint?

11.3k views Asked by At

I have a WCF Service which exposes an endpoint using the webHttpBinding and is consumed by both WPF and ASP.NET applications. Everything works great.

I am now attempting to consume the service from Windows Phone (WP7). However, as the .NET Framework hasn't quite caught up to WP7 yet, the System.ServiceModel.Web namespace is unavailable with the result that the webHttpBinding doesn't work in WP7.

Now, on my service, if I switch the webHttpBinding out for a basicHttpBinding, the phone application works.

I do not want to have to rework my WPF and ASP.NET applications to use the basicHttpBinding though.

I understand that WCF is capable of supporting multiple bindings and I have attempted to configure and run the service so that it exposes endpoints for both webHttpBinding and basicHttpBinding. The service appears to start up fine. However, the WPF & ASP.NET applications are unable to access it. And when I attempt to create a Service Reference in the WP7 application I get the following message:

A binding instance has already been associated to listen URI 'http://localhost:1726/GeneralService.svc'. If two endpoints want to share the same ListenUri, they must also share the same binding object instance. The two conflicting endpoints were either specified in AddServiceEndpoint() calls, in a config file, or a combination of AddServiceEndpoint() and config.

A colleague and I have played around with a variety of changes to the baseAddress, address, and listenUri attributes without any luck. We are now at the point of just trial and error which isn't proving to be very effective.

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

There are 4 answers

2
Rajesh On BEST ANSWER

Just specify the address attribute with a value for either basic or webhttp endpoint that would distinguish its address. Ex:

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

should resolve your problem

0
Anatolii Gabuza On

For usage service on WP you should expose your service with Rest, Soap or OData endpoints. In the link below it is quite clear described how to expose WCF RIA for such purposes:
Exposing WCF (SOAP\WSDL) Services
It works great for me.

2
Pavan Kumar Aryasomayajulu On

When defining your endpoints for the first one you are specifying address="" and for second you dont have any value(So even for this one we will have address as "")

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

So in that case when we specify address as empty it will take default base address.

So try to specify some value for anyone of the endpoints. So that we will have different address for these 2 endpoints.

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

So our new endpoints address are:

  1. http://localhost:1726/GeneralService.svc
  2. http://localhost:1726/GeneralService.svc/WP7Service
0
Aske B. On

What I was missing was protocolMapping for both endpoints:

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