Multiple WCF service endpoints in IIS breaks wcftestclient - wcf

I'm trying to expose a WCF service through both http and net.tcp binding in IIS.
Everything seems to work as expected when I specify just the net.tcp bindings, or just the http bindings, but when I add both the wcftestclient program and all other service proxy generators fail:
Error: Cannot obtain Metadata from net.tcp://host/application/service.svc
...
Metadata Exchange Error URI: net.tcp://host/application/service.svc Metadata contains a reference that cannot be resolved: 'net.tcp://host/application/service.svc '. There was > no endpoint listening at net.tcp://host/application/service.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
My web.config looks like this:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="ServiceBehavior" name="MyServiceBehavior">
<endpoint address="mex-http" binding="mexHttpBinding" name="mex-http" contract="IMetadataExchange" />
<endpoint address="service-http" binding="basicHttpBinding" name="db-http" contract="IMyService" />
<endpoint address="mex-tcp" binding="mexTcpBinding" name="mex-http" contract="IMetadataExchange" />
<endpoint address="service-tcp" binding="netTcpBinding" name="db-http" contract="IMyService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
So, if I remove the mex-http and db-http endpoints, everything is fine. If I don't, the service is accessible over http but not over tcp. If I remove the tcp endpoints, of course the http one is still available. Any thoughts?
Edit:
Based on Marc's suggestion, I changed the relevant net.tcp endpoints to read
<endpoint name="mex-http" address="net.tcp://localhost/myservice/MyService.svc/mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<endpoint name="db-http" address="net.tcp://localhost/myservice/MyService.svc" binding="netTcpBinding" contract="IMyService" />
which works as expected!

Have you checked out
How to: Host a WCF Service in WAS, and
How to: Install and Configure WCF Activation Components
Have you completed those steps to make net.tcp available in IIS / WAS?
Assuming you have - I believe hosting a net.tcp WCF service in WAS requires you to either define a net.tcp base address and/or complete addresses on the net.tcp endpoints - since those things are not defined by the IIS virtual directory.
So try:
<services>
<service behaviorConfiguration="ServiceBehavior" name="MyServiceBehavior">
...(your http stuff here)....
<endpoint name="mex-http"
address="net.tcp://YourServer:7171/NetTcpService/mex"
binding="mexTcpBinding"
contract="IMetadataExchange" />
<endpoint name="db-http"
address="net.tcp://YourServer:7171/NetTcpService/MyService"
binding="netTcpBinding"
contract="IMyService" />
</service>
</services>
or:
<services>
<service behaviorConfiguration="ServiceBehavior" name="MyServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://YourServer:7171/NetTcpService"/>
</baseAddresses>
</host>
...(your http stuff here)....
<endpoint name="mex-http"
address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange" />
<endpoint name="db-http"
address="MyService"
binding="netTcpBinding"
contract="IMyService" />
</service>
</services>

Related

wcf failed to add a service. service metadata may not be accessible

i am new in wcf.i have simple wcf service for like calculator for add,substract,muliply,division etc. i have two endpoint in my service config file. one is basicHttpBinding and another one is netTcpBinding. when i am hitting f5 then wcf test client appear and showing the error wcf failed to add a service. service metadata may not be accessible but if i off the netTcpBinding and mex for netTcpBinding and hit f5 then wcf test client can invoke the service. here is my config entry. so please have a look and tell me why i am getting error for netTcpBinding and how to fix it.
<?xml version="1.0"?>
<!--Copyright (c) Microsoft Corporation. All Rights Reserved.-->
<configuration>
<system.serviceModel>
<services>
<service name="MyTcpActivation.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="PortSharingBinding"
contract="MyTcpActivation.ICalculator"/>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
<endpoint address="" binding="basicHttpBinding" contract="MyTcpActivation.ICalculator" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="" portSharingEnabled="true">
<security mode="None"/>
</binding>
</netTcpBinding>
</bindings>
<!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.web>
<compilation debug="true"/></system.web></configuration>
please guide me where to fix in config file as a result there should no issue whatever binding i use. thanks
I think ... if you have two "IMetadataExchange" endpoints, then you need to provide different addresses. For example:
<service name="MyTcpActivation.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="PortSharingBinding" contract="MyTcpActivation.ICalculator"/>
<endpoint address="mex1" binding="mexTcpBinding" contract="IMetadataExchange"/>
<endpoint address="" binding="basicHttpBinding" contract="MyTcpActivation.ICalculator" />
<endpoint address="mex2" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>

How is the Binding done when specifying multiple Base Address

I have a WCF Service which has it's configuration file as specified below:
<system.serviceModel>
<services>
<service name="WCFService.ServiceClass" behaviorConfiguration="metaDataSupport">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/WCFService"/>
<add baseAddress="net.tcp://localhost:8100/WCFService"/>
<add baseAddress="http://localhost:8101/WCFService"/>
</baseAddresses>
</host>
<endpoint address="tcpmex"
binding="mexTcpBinding"
contract="IMetadataExchange" />
<endpoint address="namedpipemex"
binding="mexNamedPipeBinding"
contract="IMetadataExchange" />
<endpoint address=""
binding="wsHttpBinding"
contract="WCFService.IServiceClass" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="metaDataSupport">
<serviceMetadata httpGetEnabled="false" httpGetUrl="" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I have 3 types of binding here: NamedPipeBinding, TcpBinding and wsHttpBinding.
I can add a reference with metadata at the following location
net.tcp://localhost:8100/WCFService/tcpmex
net.pipe://localhost/WCFService/namedpipemex
I have disabled the httpGet for the service in behavior.
The service reference is added but with the following configuration at client:
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="WSHttpBinding_IServiceClass" />
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8101/WCFService" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IServiceClass" contract="TCP.IServiceClass"
name="WSHttpBinding_IServiceClass">
</endpoint>
</client>
</system.serviceModel>
But since I added a reference using TCP Binding endpoint,
I expected :
address=net.tcp://localhost:8100/WCFService
and binding="mexTcpBinding"
The Service is working but I would like to know, What's going on here.
What is the reason for this. Is it due to the baseAddress or some preference is given to wsHttpBinding?
Thoughts are appreciated.
Thanks.
The mex binding (short for Metadata EXchange) is not an endpoint which can be used to consume your service. Instead, it's used only used to expose information (or meta information) about all the "real" endpoints of your service - notice that your service class doesn't implement the IMetadataExchange contract which you defined in your TCP/Pipe endpoints.
In your case, your service has only one "real" endpoint - the one using wsHttpBinding, which implements the WCFService.IServiceClass interface. That's why there's only one endpoint in your client configuration.
Now, if you had another endpoint using a non-metadata binding (and not the IMetadataExchange contract), they would show up in the client config as well:
<system.serviceModel>
<services>
<service name="WCFService.ServiceClass" behaviorConfiguration="metaDataSupport">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/WCFService"/>
<add baseAddress="net.tcp://localhost:8100/WCFService"/>
<add baseAddress="http://localhost:8101/WCFService"/>
</baseAddresses>
</host>
<endpoint address="tcpmex"
binding="mexTcpBinding"
contract="IMetadataExchange" />
<endpoint address="namedpipemex"
binding="mexNamedPipeBinding"
contract="IMetadataExchange" />
<endpoint address=""
binding="netNamedPipeBinding"
contract="WCFService.IServiceClass" />
<endpoint address=""
binding="netTcpBinding"
contract="WCFService.IServiceClass" />
<endpoint address=""
binding="wsHttpBinding"
contract="WCFService.IServiceClass" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="metaDataSupport">
<serviceMetadata httpGetEnabled="false" httpGetUrl="" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

WCF error : A registration already exists for URI

Below is my WCF service configuration. I use 2 ServiceHost to host 2 service types. They use the same base address, but they use different relative addresses for their endpoints.
But I got this error, why?
Service cannot be started. System.InvalidOperationException: The ChannelDispatcher at 'http://earth:1111/' with contract(s) '"IHttpGetHelpPageAndMetadataContract"' is unable to open its IChannelListener. ---> System.InvalidOperationException: A registration already exists for URI 'http://earth:1111/'.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="serviceBehavior" name="Distributed.Troubleshooting.System.IIS.IISServiceType">
<endpoint address="iis" binding="basicHttpBinding" name="iis"
contract="Distributed.Troubleshooting.System.IIS.IISServiceContract" />
<endpoint address="iismex" binding="mexHttpBinding" bindingConfiguration=""
name="iismex" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://Earth:1111/" />
</baseAddresses>
</host>
</service>
<service behaviorConfiguration="serviceBehavior" name="Distributed.Troubleshooting.System.SQL.SQLServiceType">
<endpoint address="sql" binding="basicHttpBinding" name="sql"
contract="Distributed.Troubleshooting.System.SQL.SQLServiceContract" />
<endpoint address="sqlmex" binding="mexHttpBinding" bindingConfiguration=""
name="sqlmex" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://Earth:1111/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
Some even more ridiculous findings:
I changed my configuration to this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="serviceBehavior" name="Distributed.Troubleshooting.System.IIS.IISServiceType">
<endpoint address="http://Earth:1111/iis" binding="basicHttpBinding" name="iis"
contract="Distributed.Troubleshooting.System.IIS.IISServiceContract" />
<endpoint address="http://Earth:1111/iismex" binding="mexHttpBinding" bindingConfiguration=""
name="iismex" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://Earth:1111/iis" />
</baseAddresses>
</host>
</service>
<service behaviorConfiguration="serviceBehavior" name="Distributed.Troubleshooting.System.SQL.SQLServiceType">
<endpoint address="http://Earth:1111/sql" binding="basicHttpBinding" name="sql"
contract="Distributed.Troubleshooting.System.SQL.SQLServiceContract" />
<endpoint address="http://Earth:1111/sqlmex" binding="mexHttpBinding" bindingConfiguration=""
name="sqlmex" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://Earth:1111/sql" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
Then I found I can use "Add Service Reference" in Visual Studio with the following addresses:
http://Earth:1111/iis
http://Earth:1111/iismex
http://Earth:1111/sql
http://Earth:1111/sqlmex
It is possible to host more than one Service with the same base address. Set the HttpHelpPageEnabled and the HttpsHelpPageEnabled properties of all ServiceDebugBehaviors to false, then it should work.
Atention: By default, there's always a ServiceDebugBehavior registered in the behavior's description collection of a host even if it is not specified explicitely (I tried it only with programatic configration and the ServiceHost class, not via XML config). So, you should add an explicit ServiceDebugBehavior and set the mentioned properties. The IncludeExceptionDetailInFaults property can be true.
Have you tried removing one of the Service blocks and combining the endpoints into one?
I cant see any reason why you have them seperated.
Make sure the baseaddress + endpoint address are unique.
You can't host two services with the same base address.
You need to host the other one on a different port or address.
Something like
http://Earth:1111/Service1
and
http://Earth:1111/Service2
I don't really know why this is the case but one solution is to leave the service with no base address and to specify the full address for the endpoints. This doesn't change the address of the different endpoints, nor the addresses unicity. I could not find any relevant reference for this on MSDN.
From my own experience, the problem appears with http and not with net.tcp. I am not using service metadata. I thought the "IHttpGetHelpPageAndMetadataContract" has to do with metadata but found no way to disable it.
You'll also get this error if you accidentally start the same service twice rather than start the two different services.

How to configure basicHttpBinding for WCF service

I have a WCF service that I'm trying to get to work with wcf, old soap and plain xml. The service is called TestService.svc and the configuration looks like this:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="TestServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="poxBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="TestServiceBehavior" name="TestService">
<endpoint address="" binding="wsHttpBinding" contract="ITestService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="xml" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="ITestService"/>
</service>
</services>
</system.serviceModel>
I got this code from this other question:
REST / SOAP endpoints for a WCF service
Now, the XML webHttpBinding seems to work well, but the wsHttpBinding and basicHttpBinding does not work very well.
I can browser to the service using:
http://localhost:8295/WCFTest/TestService.svc
I can also use that endpoint to add a service reference in an asp.net web site project and attempt to consume the service, but when I create the client:
TestService.TestServiceClient mytest = new TestService.TestServiceClient();
It says to specify an endpoint due to multiple endpoints. I guess due to having both wsHttp and basicHttp? How do I specify the endpoint here?
Next I try to consume the basicHttpBinding endpoint by adding a Web Reference (not service reference) to a .net 2.0 web site. At this point I'm not able to add the reference and receive an error 400.
So next I remove the wsHttp binding and am able to add the web reference and consume the service via a .net 2.0 client.
How do I configure it so that I can use wsHttpBinding for clients that can consume normal WCF services, basicHttpBinding for clients that can only consume older non-WCF SOAP requests and still have webHttpBinding available for clients that want to consume plain xml?
The person who posted this link (http://www.codemeit.com/wcf/wcf-restful-pox-json-and-soap-coexist.html) appears to be correct. But since this question remains unanswered, I'll elaborate a bit.
If you haven't tried it, I will mention first that nowhere in your configuration do you specify an actual address for the client service to connect to.
<service behaviorConfiguration="TestServiceBehavior" name="TestService">
<endpoint address="" binding="wsHttpBinding" contract="ITestService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="xml" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="ITestService"/>
</service>
Your first endpoint has
<endpoint address="" binding="wsHttpBinding" contract="ITestService">
Based on documentation on MSDN (found here) and the link above, it appears that you are missing this in your service configuration
<host>
<baseAddresses>
<!-- note, choose an available port-->
<add baseAddress="http://localhost:8295/WCFTest/TestService" />
</baseAddresses>
</host>
Adding that would make your service configuration look like this
<service behaviorConfiguration="TestServiceBehavior" name="TestService">
<host>
<baseAddresses>
<!-- note, choose an available port-->
<add baseAddress="http://localhost:81/TestService" />
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="ITestService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="xml" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="ITestService"/>
</service>
Adding that section will provide the address to use, while the specific endpoints will then use addresses relative to the base address provided.

Do WCF Services have to have a MetaDataExchange endpoint for each service or can I have just one?

If my WCF Configuration file has two services, lets says LoginService and RegistrationService, do they both have to have their own MetaDataExchange endpoint or can I just have one MetaDataExchange endpoint and keep it outside the service element:
<services>
<service name="a">
<endpoint binding="mexHttpBinding" />
</service>
<service name="b">
<endpoint binding="mexHttpBinding" />
</service>
<services>
Or is this valid as well:
<services>
<service name="a">
</service>
<service name="b">
</service>
<endpoint binding="mexHttpBinding" />
<services>
The first one.
When you add a service reference, it is for a service not for all services on a server.