wcftestclient fails, but only on remote machine - wcf

I've got a wcf "self-hosted" service up and running and when communicating across machines i get The remote server returned an unexpected response: (405) Method not allowed. message.
This only seems to happen when running the WCF test client connecting to a remote machine. When running on the server, everything communicates fine.
i'm thinking it has something to do with security, but i'm not sure where to look.
Can anyone point out what i'm missing or doing wrong?
below is my server config file
<system.serviceModel>
<protocolMapping>
<remove scheme="http" />
<add scheme="http" binding="customBinding" bindingConfiguration="gzipCompression" />
</protocolMapping>
<bindings>
<customBinding>
<binding name="gzipCompression">
<gzipMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" />
</binding>
</customBinding>
</bindings>
<extensions>
<bindingElementExtensions>
<add name="gzipMessageEncoding" type="Compression.GZIP.GZipMessageEncodingElement, Compression, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bindingElementExtensions>
</extensions>
<behaviors>
<!--<serviceBehaviors>
<behavior name="CadServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"
httpGetBinding="" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>-->
</behaviors>
<services>
<service behaviorConfiguration="CadServiceBehavior" name="CadServiceLibrary.CadServiceContract">
<endpoint address="com" binding="customBinding" bindingConfiguration="gzipCompression"
name="com" contract="CadServiceLibrary.CadServiceContract" />
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
name="mex" contract="IMetadataExchange" />
<endpoint binding="wsHttpBinding" bindingConfiguration="" name="ws"
contract="CadServiceLibrary.CadServiceContract" />
<host>
<baseAddresses>
<add baseAddress="http://localhost/CadServices" />
<add baseAddress="https://localhost:450/CadServices" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>

I have seen this before although not sure if it is your problem:
Instead of localhost, put your server's name or IP address. If IP address, make sure the same IP address is selected in IIS (I assume you are hosting this in IIS).
When localhost is used, I have had difficulty in the past accessing it from remote machines - although listening on localhost works fine with TCP.

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 enable http and https with wcf service?

I need publish a wcf service, and this should be accessed with Http and Https protocols.
I tried to configure this in my server, but the problem with is that only one of this protocols can work.
Is it possible?
This is my Web.config code:
<bindings>
<basicHttpBinding>
<binding name="basicHttpBindingConfiguration">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviorConfiguration">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="ServiceBehaviorConfiguration" >
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpBindingConfiguration" name="TestSvc" contract="ServiceTest.ITest" />
</service>
</services>
It's possible, but in a way you might not expect. You host your service on HTTPS. Then create another site on the same pool. This site is HTTP and it contains only web.config file looking like this
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<httpRedirect enabled="true" destination="https://your_https_url" exactDestination="true" childOnly="false" />
</system.webServer>
</configuration>
Now every time someone tries to use the HTTP site will be automatically redirected to HTTPS.
Try using multiple endpoints for same service one with basicHttpBindind and one with wsHttpBinding
<service name="NorthwindServices.Services.CustomerService"
behaviorConfiguration ="ServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:7741/NorthwindServices/Services
/CustomerService" />
<add baseAddress="https://localhost:4512/Services/CustomerService" />
</baseAddresses>
</host>
<endpoint address ="" binding="wsHttpBinding"
contract="NorthwindServices.ServiceContracts.ICustomerService"
bindingNamespace = "http://dotnetmentors.com/services/customer" />
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
<endpoint address ="" binding ="basicHttpBinding"
contract ="NorthwindServices.ServiceContracts.ICustomerService"
bindingNamespace = "http://dotnetmentors.com/services/customer" />
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>

Modify Program Using Sync Framework to use WCF

I'm trying to synchronize a client database with a central database. I successfully did that using the Synchronization framework as long as both the client and central database are on the same network. However, I need for this to work with the client being outside the network and the firewall. The firewall prevents communications on port 1433, so I started to explore WCF as an option so port 80 is used.
I tried this and put the WCF service under IIS 7:
http://code.msdn.microsoft.com/Database-SyncSQL-Server-e97d1208
but have gotten this error:
Failed: The caller was not authenticated by the service.
I searched high and low for a solution to this error but have found none. Does anyone know a tutorial on how to use the sync framework over WCF?
Here is the web.config file on the IIS server:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<httpRuntime maxRequestLength="65536" />
<customErrors mode="Off" />
</system.web>
<system.serviceModel>
<services>
<service behaviorConfiguration="WebSyncContract.SqlWebSyncService" name="WebSyncContract.SqlWebSyncService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="largeMessageHttpBinding" contract="WebSyncContract.ISqlSyncContract">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://web-services.hexagroup.us/WebSyncContract.SqlWebSyncService.svc" />
</baseAddresses>
</host>
</service>
<service name="WebSyncContract.SqlSyncProviderProxy" behaviorConfiguration="WebSyncContract.SqlSyncProviderProxy" >
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
<service behaviorConfiguration="WebSyncContract.SyncService" name="WebSyncContract.SyncService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="largeMessageHttpBinding" contract="WebSyncContract.ISyncContract">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<!--<add baseAddress="http://localhost:8080/"/>-->
<add baseAddress="http://web-services.hexagroup.us/WebSyncContract.SqlWebSyncService.svc" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<wsHttpBinding>
<!-- We are using Server cert only.-->
<binding name="largeMessageHttpBinding" maxReceivedMessageSize="2147483647" receiveTimeout="00:10:00" sendTimeout="00:10:00">
<readerQuotas maxArrayLength="2147483647" />
<!--<reliableSession enabled="true" />
<security mode="None" />-->
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="WebSyncContract.SqlWebSyncService">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True" />
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
<behavior name="WebSyncContract.SqlSyncProviderProxy" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
<behavior name="WebSyncContract.SyncService" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true" />
</system.webServer>
</configuration>

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.

WCF SSL certificate validation error

Trying to get the simple Hello World (via SSL) working but receiving a following error: The remote certificate is invalid according to the validation procedure.
The server App.config is:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="mexBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="SSLSecurity">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="mexBehavior" name="HelloServiceLibrary.HelloService">
<clear />
<endpoint address="ws" binding="wsHttpBinding" name="wsEndpoint"
contract="HelloServiceLibrary.IHelloService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="https://localhost:443/hellossl" binding="wsHttpBinding" name="wssslEndpoint"
bindingConfiguration="SSLSecurity" contract="HelloServiceLibrary.IHelloService">
<identity>
<certificateReference x509FindType="FindByThumbprint" findValue="‎82a39faaeb18bf9585b334ca83264add3d5b26ee" />
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" name="mexEndpoint"
contract="IMetadataExchange">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8989/hello" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
Please advice what am I doing wrong.
Update: the certificate is successfully deployed in Trusted Root Certification Authorities on local computer.
Add this to your WCF config and let me know the output.
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.Net" maxdatasize="1024">
<listeners>
<add name="MyTraceFile"/>
</listeners>
</source>
<source name="System.Net.Sockets" maxdatasize="1024">
<listeners>
<add name="MyTraceFile"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add
name="MyTraceFile"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="System.Net.trace.log"
/>
</sharedListeners>
<switches>
<add name="System.Net" value="Verbose" />
<add name="System.Net.Sockets" value="Verbose" />
</switches>
</system.diagnostics>
This is a stab in the dark.
Check to make sure you installed it to all users.
Open up MMC
Add Snap In (Certificates)
- Check Computer Account (Next)
- Choose your computer
Done
Now reinstall the cert to "Trusted Root Certification Authorities" and it will be trusted for all users.
Not sure if this may help you but I looked back at how I had my app.config set for a simple secure service I wrote a few weeks ago where I was using certs. Here are a few considerations you may need to make to properly config your config for the service:
<bindings>
<wsHttpBinding>
...
<security>
<transport clientCredentialType="Certificate" />
</security>
</wsHttpBinding>
</bindings>
Now in my config I have an endpoint behavior defined which provides metadata to tell the service what the client will be using for a cert on its side:
<behaviors>
<endpointBehaviors>
<behavior name="ClientBehavior">
<clientCredentials>
<clientCertificate findValue="WcfClient" storeLocation="LocalMachine" storeName="My"
x509FindType="FindBySubjectName"/>
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
If all you need is a secure link, i.e. encryption only, no client authentication, then you don't need to set any client credentials. This is all you should have to do:
1. configure IIS to use SSL
2. configure an HTTPS endpoint on your service
3. configure the client to use the above endpoint
That's it. If your certificate is invalid, you might have to do your custom certificate validation as described here: MSDN.
Good luck!