WCF IMetadataExchange Error - wcf

I have created a service host with following configuration.
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="MathServiceLib.MathService" behaviorConfiguration="myMathServiceBehave">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9001/MathService"/>
<add baseAddress="net.tcp://localhost:9002/MathService"/>
</baseAddresses>
</host>
<endpoint address="http://localhost:9001/MathService" binding="basicHttpBinding" contract="MathServiceLib.IMathService"/>
<endpoint address ="net.tcp://localhost:9002/MathService" binding ="netTcpBinding" contract="MathServiceLib.IMathService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<!--<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>-->
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="myMathServiceBehave">
<!--<serviceMetadata httpGetEnabled="true"/>-->
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I don't want to use serviceMetadata httpGetEnabled="true" property instead I want to use MEX binding for proxy creation.
Now when I start my service using
svcHost = new ServiceHost(typeof(MathServiceLib.MathService));
svcHost.Open();
I get following error, please help.
The contract name 'IMetadataExchange' could not be found in the list of contracts implemented by the service MathService. Add a ServiceMetadataBehavior to the configuration file or to the ServiceHost directly to enable support for this contract.

Based on my experience, you need to specify
<serviceMetadata httpGetEnabled="true"/>
if you want to use
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
The following articles provide comprehensive information and examples:
http://msdn.microsoft.com/en-us/library/ms734765(v=vs.110).aspx
http://www.c-sharpcorner.com/UploadFile/81a718/wcf-service-faqs-part-2/

Related

WCF use netTcpBinding in IIS

I follow this blog CONFIGURING WCF SERVICE WITH NETTCPBINDING step by step, when I add service reference from VS 2013, I got below error.
The URI prefix is not recognized.
Metadata contains a reference that cannot be resolved: 'net.tcp://localhost/WCFNetTcp/WCFNetTcpService.svc/mex'.
You have tried to create a channel to a service that does not support .Net Framing. It is possible that you are encountering an HTTP endpoint.
Expected record type 'PreambleAck', found '72'.
My Service configure file is below:
<system.serviceModel>
<services>
<service behaviorConfiguration="netTcpb" name="WCFNetTcp.WCFNetTcpService">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="portSharingBinding" contract="WCFNetTcp.IWCFNetTcpService" />
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange" />
<!--<endpoint address="mexHttp" binding="mexHttpBinding" contract="IMetadataExchange" />-->
<host>
<baseAddresses>
<!--<add baseAddress="net.tcp://localhost:6666/WCFNetTcpService/"/>-->
<add baseAddress="net.tcp://localhost:808/WCFNetTcp/WCFNetTcpService.svc" />
<!--<add baseAddress="http://local/WCFNetTcp"/>-->
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="netTcpb">
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="portSharingBinding" portSharingEnabled="true"/>
</netTcpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
<baseAddressPrefixFilters>
<add prefix="net.tcp://localhost:808"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
</system.serviceModel>
I tried any net.tcp URL what I could think out, but all of them do not work. It seems that basic address did not work when the service is hosted in IIS, it depends on the url in IIS. If I create a service which is hosted in console application with below configuration file, it works.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="WCFNETTCP.Service1">
<endpoint address="" binding="netTcpBinding" contract="WCFNETTCP.IService1">
</endpoint>
<!--comment out after you add service reference-->
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://xxx:6666/WCFNETTCP/" />
<add baseAddress="http://xxx:6667/WCFNETTCIP"/>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
It would be appreciated if you could share us how to make it work under IIS.
It seems there is something wrong in my IIS. I resolved this issue by below steps.
reinstall IIS
reinstall WCF Non-HTTP Activation in Windows features
reregister asp.net in iis by this command
C:\Windows\Microsoft.NET\Framework64\v4.0.30319>dism /online /enable-feature /featurename:IIS-ASPNET45
Check the settings in IIS which there is no change at my side.
Rebuild my WCF Service, and add service reference successfully.
Hope it will be work for you.

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 cannot configure WSDL publishing

I want to enable WSDL retrieval for a webservice that I created. I can 'call' the webservice through the .svc file that I made:
http://localhost/test.svc
<%# ServiceHost Language="C#" Debug="true" Service="Project.MyService" CodeBehind="MyService.svc.cs" %>
Calling the page gives the standard .NET message saying "Metadata publishing for this service is currently disabled." with instructions to enable publishing.
I followed instructions and added the web.config entries, however calling http://localhost/test.svc?wsdl produces the same result... How can I enable WSDL publishing for my webservice?
web.config entries
<service name="Project.IMyService" behaviorConfiguration="MyServiceTypeBehaviors" >
<endpoint contract="IMetadataExchange" binding="mexHttpBinding"
address="mex"
/>
<host>
<baseAddresses>
<add baseAddress="http://localhost/test.svc"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
Sounds crazy but just remove behaviorConfiguration="MyServiceTypeBehaviors" from the service definition andlet the behavior anonymous (with no name). It will remain
<services>
<service name="WcfServiceLibrary1.IMyService" >
<endpoint contract="IMetadataExchange" binding="mexHttpBinding"
address="mex"
/>
<host>
<baseAddresses>
<add baseAddress="http://localhost/test.svc"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
The mex endpoint and httpGetEnabled look ok. This link covers the topic in some more detail and may be of use.
http://msdn.microsoft.com/en-us/library/ms788760.aspx

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 can I use IMetadataExchange endpoint to get information about service metadata?

How can I use IMetadataExchange endpoint to get information about service metadata?
Do I need to implement it in a class like we do for other interfaces ?
Please help me ...
The framework will take care of the implementation for you.
However, you must create a service behavior that enables this.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<!-- behavior that enables metadata exchanges -->
<behavior name="mexGet">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<!-- assign the custom behavior here -->
<service name="MyNamespace.MyImplementation"
behaviorConfiguration="mexGet">
<host>
<baseAddresses>
<add baseAddress="http://localhost:3849"/>
</baseAddresses>
</host>
<endpoint
address="MyService"
binding="wsHttpBinding"
contract="MyNamespace.MyServiceInterface"
>
</endpoint>
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange">
</endpoint>
</service>
</services>
</system.serviceModel>
</configuration>
No, just add the endpoint that exposes IMetadataExchange. You don't have to implement anything.
No need to implement 'IMetadataExchange'. Just add endpoint:
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
One important thing, you must declare serviceMetadata, or your IMetadataExchange will not be found:
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata />
</behavior>
</serviceBehaviors>
</behaviors>