WCF Test Client fails to add service - Cannot obtain Metadata - web-services

I see there are quite a few questions regarding this particular problem. I have spent a day and a half trying all the different suggestions. None so far have worked for me and I'm at a loss as to what to do next. So I'm appealing to the vast knowledge base found here with the hopes that somebody will see the problem and help me out. At one time, a couple of years ago, I had this all working for me, several PCs ago. But when I had to change to a new PC, I was unable to make it work then or any time since but was able to work around it. Now I need to resolve this for a current assignment.
I have a SOAP WCF WebService running in IIS (not IIS Express) on my local machine.
I created an App Pool. Basic Settings are .NET Framework v4.0.30319 with Integrated pipeline mode. Advanced settings have Identity set to ApplicationPoolIdentity.
I created a website (not using the default website.)
Two bindings defined:
We have a client and a Service self-signed certs that we use for development and QA. I have the Service cert assigned to the https binding. The webservice communicates to another wcf service via net.tcp.
In the basic settings, I have defined the physical path to c:\inetpub\websitename. In order to connect successfully, using Test Settings..., I had to connect as a Specific User, using my network domain userid and password. I haven't yet found a way to get around that.
In Advanced Settings.... Application Pool is set to the app pool I created. Physical path is c:\inetpub\wwwroot\websitename. Enabled Protocols set to http,net.tcp.
I am able to browse successfully to the website.
Here is the web.config for the web service:
<system.serviceModel>
<client>
<endpoint address="net.tcp://10.100.13.28:8102/Acord/201307" behaviorConfiguration="NetTcpCertificatesBehavior" binding="netTcpBinding" bindingConfiguration="NetTcpCertificatesBinding" contract="AcordContract.IAcordService201307" name="AcordEndpoint">
<identity>
<certificateReference findValue="7da522dd75f3fca2687837b7b67e117a8700ec62" isChainIncluded="false" storeLocation="LocalMachine" x509FindType="FindByThumbprint" />
<!--<dns value="localhost" />-->
</identity>
</endpoint>
<endpoint address="net.tcp://qaschedapp:8002/IMS/201210" behaviorConfiguration="NetTcpCertificatesBehavior" binding="netTcpBinding" bindingConfiguration="NetTcpCertificatesBinding" contract="IdentityManagementContract.IIdentityManagementService201210" name="IMSEndpoint">
<identity>
<certificateReference findValue="7da522dd75f3fca2687837b7b67e117a8700ec62" isChainIncluded="false" storeLocation="LocalMachine" x509FindType="FindByThumbprint" />
</identity>
</endpoint>
</client>
<services>
<service name="AcordWebService.AcordWebService" behaviorConfiguration="Visible">
<endpoint address="" binding="basicHttpsBinding" contract="AcordWebService.IAcordWebService201307" bindingConfiguration="BasicHttpsBinding">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://10.100.13.28:51448/" />
</baseAddresses>
</host>
<!--binding for clients outside the firewall calling from C# with WCF using certs -->
<endpoint address="net.tcp://10.100.13.28:8122/AcordWebService.svc" binding="netTcpBinding" bindingConfiguration="NetTcpCertificatesBinding" name="NetTcpCertificatesEndpoint" contract="AcordWSContract.IAcordWSService201309">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="NetTcpCertificatesBehavior">
<clientCredentials>
<clientCertificate findValue="631f5a67a9a70bc78540bb809e73fd1dbd00bbeb" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
<serviceCertificate>
<authentication certificateValidationMode="None" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Visible">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" httpGetUrl=""/>
<!-- 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"/>
<serviceCredentials>
<serviceCertificate findValue="7da522dd75f3fca2687837b7b67e117a8700ec62" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint"/>
<clientCertificate>
<certificate findValue="631f5a67a9a70bc78540bb809e73fd1dbd00bbeb" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpsBinding>
<!--binding for clients within the firewall but calling the old style soap service-->
<binding name="BasicHttpsBinding" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpsBinding>
<netTcpBinding>
<binding name="NetTcpCertificatesBinding" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<!--<readerQuotas maxDepth="32" maxStringContentLength="65535" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />-->
<!--<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />-->
<security>
<transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign" />
</security>
</binding>
</netTcpBinding>
</bindings>
<protocolMapping>
<add binding="wsHttpBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
Here is the full error I am receiving when trying to add a service to the WCF Test Client:
Error: Cannot obtain Metadata from https://10.100.13.28:51448/AcordWebService.svc If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange Error URI: https://10.100.13.28:51448/AcordWebService.svc Metadata contains a reference that cannot be resolved: 'https://10.100.13.28:51448/AcordWebService.svc'. Could not establish trust relationship for the SSL/TLS secure channel with authority '10.100.13.28:51448'. The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. The remote certificate is invalid according to the validation procedure.HTTP GET Error URI: https://10.100.13.28:51448/AcordWebService.svc There was an error downloading 'https://10.100.13.28:51448/AcordWebService.svc'. The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. The remote certificate is invalid according to the validation procedure.
Lastly, to fill in a few holes in the information:
Any and all help will be appreciated if I'm able to finally resolve this problem.
Thanks in advance.

Here is how I solved my problem:
First, I had to turn on logging in my web.config:
<system.serviceModel>
<diagnostics>
<messageLogging maxMessagesToLog="30000" logEntireMessage="true"
logMessagesAtServiceLevel="true"
logMalformedMessages="true"
logMessagesAtTransportLevel="true"
maxSizeOfMessageToLog="65535000">
</messageLogging>
</diagnostics>
</system.serviceModel>
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Verbose, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener" />
</listeners>
</source>
</sources>
<sharedListeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\logs\Traces.svclog" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>
Then checking the generated log I finally discovered that my web service's constructor was failing attempting to initialize NLog. Ultimately, I discovered that NLog was attempting to write to EventLog for which it did not have permissions. I followed the instructions found here except that I granted the permissions to the IIS AppPool user. This solved my problem.

Related

how to make wcf working web service to work on https ?

I wrote some wcf web service that work good ( restful ).
I need now to support the calling of those web service only from https
The configuration file code:
<service name="Microsoft.ServiceModel.Samples.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/ServiceModelSamples/service"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="Microsoft.ServiceModel.Samples.ICalculator" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
Here are the steps with which you can enable SSL.
First create a self signed certificate,You can use IIS manager to do it.
Open INETMGR and then open Server Certificates then proceed to create self signed certificate,say the name is testcertificate.
Now in your wcf configuration file would be like this
<system.serviceModel>
<services>
<service name="NorthwindServices.ProductService">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="NorthwindServices.IProducts"/>
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Note I have changed below things
1) In serviceBehaviors for allowing https request I set httpsGetEnabled="true".
2) Set clientCredentialType as None to specify anonymous authentication which does not perform client authetication. The possible values for clientCredentialType are None, Basic, Digest, Ntlm, Windows.
Finally you can host the service in IIS.
In IIS right click on the site and click on Edit Bindings,Now click on Add
button and select https from type dropdown of Add Site Binding window.
From SSL Certificate drop down select testcertificate which you created in first step. Click Ok and close Site Bindings window.
Publish wcf in localhost.

Exposing RESTful WCF service over HTTPS

I've poked around dozens of blogs and SO questions and still can't get this to work. I can load my service over HTTP, but I get the following error over HTTPS:
Could not find a base address that matches scheme http for the endpoint with binding secureWeb. Registered base address schemes are [https].
I'm hosting locally in IIS under an SSL site that works for several other apps already. Here is the config that I am trying to get working; any suggestions would be greatly appreciated!
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="secureWeb">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" httpHelpPageEnabled="false" httpsHelpPageEnabled="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="Example.TestService">
<endpoint binding="webHttpBinding" bindingName="secureWeb" bindingNamespace="http://example.com/services"
behaviorConfiguration="webBehavior"
contract="Example.ITestService" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
<serviceActivations>
<add relativeAddress="Test.svc" service="Example.TestService" factory="Example.Common.ServiceModel.Activation.FlatWsdlServiceHostFactory" />
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
In addition to everything else already said, I think you should have bindingConfiguration="secureWeb" instead of bindingName="secureWeb"
(e.g. <endpoint binding="webHttpBinding" bindingConfiguration="secureWeb"...)
Based on a review of your WCF configuration, I think the issue may be related to the service metadata configuration. The configuration seems to specify that the metadata is available via http and https, but the endpoints only contain bindings for secure https (secureWeb).
In the following line, change the httpGetEnabled value from true to false.
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
Note: The Creating a WCF RESTful Service And Secure It Using HTTPS Over SSL blog post mentions changing the service metadata options toward the end:
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
Lastly, we need to update the metadata publishing endpoint to use
HTTPS as well:

WCF Service in IIS bindings

I have inherited a WCF project which is hosted under IIS. Its part of a regular website i.e. there are human usable pages as well.
The site is configured in IIS with the following 2 bindings:
1: https://www.example.com/
2: http://www.example.com:8080/
If I visit http://www.example.com:8080/my-service.svc?wsdl I get a WSDL file returned as expected.
If I visit https://www.example.com/my-service.svc?wsdl I get told I need to visit http://www.example.com:8080/my-service.svc?wsdl to create a client.
There is no binding section under system.serviceModel in web.config.
What I want to know is, how does the service know it is associated with the second IIS binding and not the first.
system.ServiceModel follows:
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="FormsAuthBehavior" type="My-WCF.FormsAuthBehaviorExtensionElement, EcobuttonWebService" />
</behaviorExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<behavior name="FormsAuthenticated">
<!--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="false" />
<!--Pre-authenticates client with server to generate FormsAuthentication cookie. Cookie is submitted with each WCF request.-->
<!--NB: set throwsSecurityExceptions="false" when updating service references in client apps.-->
<FormsAuthBehavior throwsSecurityExceptions="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
<services>
<service name="My-Service" behaviorConfiguration="FormsAuthenticated" />
</services>
</system.serviceModel>
Configure WCF Service for HTTP Transport Security
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
Specify your service and service endpoint as shown in the following XML.
<services>
<service name="MySecureWCFService.Service1">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="MySecureWCFService.IService1"/>
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
Enable httpsGetEnabled
<serviceBehaviors>
<serviceMetadata httpsGetEnabled="true"/>
</serviceBehaviors>
References:
MSDN
Seven simple steps to enable HTTPS on WCF WsHttp bindings

Setting up Secured SSL, WCF using windows authentication

Ok, I really need help getting this setup. Currently i have an ssl cert installed. I have a wcf service installed in iis as an application. I have set it to require ssl and i am able to connect to the service. Issue is i want windows authentication. and i want to disable anonymous security. Soon as i disable anonymous and keep windows auth. i get an error:
"the authentication schemes configured on the host ('IntegratedWindowsAuthentication') do not allow those configured on the binding 'BasicHttpBinding' ('Anonymous'). Please ensure that the SecurityMode is set to Transport or TransportCredentialOnly.etc etc...."
When i turn anonymous back on with windows auth. Yes i can access the service but it doesn't use the windows auth.. its weird because other files such as test.html for example still require username/password. i don't know how to properly restrict a webservice for windows auth using ssl... can anyone help me?? please
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="TransportSecurity">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
<readerQuotas maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="WcfConcur.ConcurService">
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="TransportSecurity"
contract="WcfConcur.IConcurService"/>
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpsGetEnabled="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>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
on the client side, i add a reference to the wcf. and it downloads this automatically. thing is my intial wcf address that is hosted is https://address/whatever.svc and when it downloads it shows http://internal address i don't know if thats the issue
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client" />
</startup>
<system.serviceModel>
<client>
<endpoint address="http://internal address/wcfConcurService/ConcurService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IConcurService"
contract="wcfConcurRef.IConcurService" name="BasicHttpBinding_IConcurService" />
</client>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IConcurService" />
</basicHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
The error message thrown, when anonymous access is disabled, seems to indicate an issue with the client configuration.
The client configuration appears to be using the basicHttpBinding which is different from the server configuration which is using wsHttpBinding. To resolve the binding issue, you should copy the server binding configuration to the client configuration file and then update the client endpoint to use the new binding configuration.
Your client configuration should look something like:
<system.serviceModel>
<client>
<endpoint address="https://enter-external-address-here/wcfConcurService/ConcurService.svc"
binding="wsHttpBinding" bindingConfiguration="TransportSecurity"
contract="wcfConcurRef.IConcurService" name="BasicHttpBinding_IConcurService" />
</client>
<bindings>
<wsHttpBinding>
<binding name="TransportSecurity">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>

Make WCF webservice available over http and https using basicHttpsBinding

I'm trying to make my webservice available over http and https, but I'm running into this error:
A child element named 'endpoint' with same key already exists at the same configuration scope. Collection elements must be unique within the same configuration scope (e.g. the same application.config file). Duplicate key value: 'address:;bindingConfiguration;bindingName:;bindingNamespace:;bindingSectionName:basicHttpsBinding;contractType:RestService.Iservice;kind:;endpointConfiguration:;'.
Now, that's a clear error, but I don't know how to alter my configuration to support http and https requests on the same contract.
Notice that I wish to use the WCF4.5 basicHttpsBinding configuration.
Here's my configuration:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="RestService.service">
<!--
<host>
<baseAddresses>
<add baseAddress = "http://www.nl/service.svc/" />
<add baseAddress = "https://www.nl/service.svc/" />
</baseAddresses>
</host>
-->
<endpoint binding="webHttpBinding" contract="RestService.Iservice" />
<endpoint binding="webHttpBinding" address="" bindingConfiguration="webHttpBindingWithJsonP" name="RestService.Iservice" contract="RestService.Iservice">
</endpoint>
<endpoint binding="basicHttpsBinding" contract="RestService.Iservice" />
<endpoint binding="basicHttpsBinding" address="" name="RestService.Iservice" contract="RestService.Iservice">
</endpoint>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true">
</binding>
</webHttpBinding>
<basicHttpsBinding>
<binding name="webHttpsBindingWithJsonP">
<security mode="Transport"></security>
</binding>
</basicHttpsBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp />
</behavior>
<behavior name="webHttpBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
In your endpoints, you need to set the binding of the Json endpoints to webHttpBinding, not basicHttpBinding. For the secured endpoint, you'll need to add a binding configuration and set the security mode to transport.
Also, please set an address for either the web/basic endpoint. I'm pretty sure you cannot use those two bindings with the same address.
Lastly, since you are hosted under IIS, you can remove the baseAddress section as it is not required. And make sure your web site in IIS is configured to support the http and https protocols (check that through the web site's bindings dialog in the IIS Manager)