WCF web.config file settings for IIS hosting and SSL - wcf

After hours of searching for examples, most of which contain only snippets of methods but not the 'whole picture' I am asking for guidance. Starting with the out-of-the-box web.config Visual Studio creates with a new WCF Service, I wrote my basic web service. When you run in debug, WCF Test Client shows the functions that you can test. This is great. Now, wanting to move the code to IIS (first on my local machine, then next to the web server using SSL), I added some code I found on the web. I did have my configuration working at one point but managed to change it so much that I lost the original configurations. So, which that, I have this:
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="webHttpBinding"/>
</protocolMapping>
<services>
<service name="TaskTrackerAppService.Service1" behaviorConfiguration="">
<endpoint address=""
binding="webHttpBinding"
contract="TaskTrackerAppService.IAppWebService"
behaviorConfiguration="WebBehavior"></endpoint>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange" bindingConfiguration=""></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="TaskTrackerAppService.IAppWebService"></binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="" binding="webHttpBinding"
bindingConfiguration="TaskTrackerAppService.IAppWebService"
contract="TaskTrackerAppService.IAppWebService"></endpoint>
</client>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
</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>
I configure my client desktop application service reference to point to the local IP http:192.168.0.100:90/AppWebService.svc. Then when I run my client application I get an error:
Could not find default endpoint element that references contract 'ServiceReference.IAppWebService' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.
So I'd like to get the web.config settings corrected. Then deploy to a hosted IIS service where SSL is ready. As a bonus, is there is way to configure the endpoints such that I can still run debugger and get WCF Test Client. In the once working config WCF test stopped working. Can it support both simple and hosted configurations?
Thanks.

The <client> section in the <system.serviceModel> is used by client application to specify the "ABC" properties (Address, Binding, and Contract) of the service endpoint. You should have that section in your desktop application so you can simply remove it from your server configurations.
The <client> section in the app.config of your desktop application should, however, have the same "ABC" properties as the service endpoint. Since your service binding is webHttpBinding the client should also have webHttpBinding as binding but I can see that the bindingConfiguration it is referring to, TaskTrackerAppService.IAppWebService is actually a basicHttpBinding so that is a misconfiguration.
Further, since your production environment is using SSL so your production web.config should have binding configuration for SSL something similar to this:
<bindings>
<webHttpBinding>
<binding name="webBindingHTTPS">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
with the following endpoint configuration:
<endpoint address=""
binding="webHttpBinding"
contract="TaskTrackerAppService.IAppWebService"
behaviorConfiguration="webBindingHTTPS"></endpoint>
The best way to achieve this is to use web.config transformation syntax. In that case, your Release web.config could have the following elements:
<bindings>
<webHttpBinding>
<binding name="webBindingHTTPS" xdt:Transform="Insert">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
<endpoint address="" xdt:Transform="Replace" xdt:Locator="Match(name)"
binding="webHttpBinding"
contract="TaskTrackerAppService.IAppWebService"
behaviorConfiguration="webBindingHTTPS">
</endpoint>
In this way, whenever you project is built in Debug mode it will be configured withoud SSL and whenever is built in Release mode, it will use SSL.

Related

WCF Rest service does not work over HTTP in IIS 8

My team has a small WCF Rest service written in .NET 4.0. Historically, it has been deployed on Server 2008 machines running IIS 7, using the following binding configuration:
<bindings>
<webHttpBinding>
<binding name="httpsBinding">
<security mode="Transport"/>
</binding>
</webHttpBinding>
</bindings>
As one would expect, the service works just fine with HTTP or HTTPS, so long as the web server is configured with bindings for each.
However, when we install the service on a Server 2012 box running IIS 8, the service will work just fine via HTTPS, but requests over HTTP fail with a 404 status.
We have looked at the IIS configuration of the Server 2008 and Server 2012 machines, but there is nothing that stands out as an obvious culprit. All the settings appear to be the same.
Is there any extra configuration that needs to be done either in IIS or in the web config? There are plenty of questions out there on SO and MSDN about services which work with HTTP and not HTTPS, but none that I have seen for the reverse.
edit:
According to the WCF trace logs, the 2008 machine opens endpoint listeners on both HTTP and HTTPS, whereas the 2012 machine only opens an endpoint listener for HTTPS.
To be sure I am not missing anything on the service itself, I have installed the same MSI on both machines and even over-wrote the web.config on the 2012 box with the one from the 2008 box (though they should have been identical anyways). There is no change in behavior.
edit 2:
Below is the web.config in its entirety:
<?xml version="1.0"?>
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<!--
The <authentication> section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
<authentication mode="None"/>
<compilation targetFramework="4.0"/>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
</system.web>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<services>
<service name="service1">
<endpoint behaviorConfiguration="webHttp" binding="webHttpBinding" bindingConfiguration="httpsBinding" contract="service1"/>
</service>
<service name="service2">
<endpoint behaviorConfiguration="webHttp" binding="webHttpBinding" bindingConfiguration="httpsBinding" contract="service2"/>
</service>
<service name="service3">
<endpoint behaviorConfiguration="webHttp" binding="webHttpBinding" bindingConfiguration="httpsBinding" contract="service3"/>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="httpsBinding">
<security mode="Transport"/>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Add an HTTP endpoint for each service like this:
<endpoint behaviorConfiguration="webHttp" binding="webHttpBinding" bindingConfiguration="httpBinding" contract="service3"/>
And associated binding for HTTP only:
<binding name="httpBinding">
<security mode="None"/>
</binding>

WCF Binding to HTTPS

I understand that there are many posts about this, and I've been through all of them that came up on my search and implemented everything that was mentioned. I have a WCF web service that works on my local system on HTTP, and it worked on the server on HTTP. But the client requires that this works through HTTPS. The miriad of posts on this and other sites shows me that this is not as straight forward as it should be, since before this, the ASMX web service "just worked" and didn't need complicated configuration.
I'm getting the following error with my current configuration:
Could not find a base address that matches scheme https for the
endpoint with binding WSHttpBinding. Registered base address schemes
are [http].
Here is my code as of this moment, after trying for days to configure this to work to no avail:
<system.serviceModel>
<!-- -->
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" >
<baseAddressPrefixFilters>
<add prefix="https://mysite.com"/>
<add prefix="http://mysite.com"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
<!-- Set up Custom Behaviors -->
<behaviors>
<endpointBehaviors>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="WebPostService.WebPostServiceBehavior">
<serviceMetadata httpsGetEnabled="true" httpsGetUrl="WebPostServices.svc/mex" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<!-- Set up the binding configuration -->
<bindings>
<wsHttpBinding>
<binding name="SOAPBinding"
>
<security mode="Transport">
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service
behaviorConfiguration="WebPostService.WebPostServiceBehavior"
name="WebPostService.WebPostService"
>
<host>
<baseAddresses>
<add baseAddress="https://mysite.com/Services/WebPostService.svc"/>
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="SOAPBinding"
contract="WebPostService.IWebPostService"
>
<identity>
<dns value="mysite.com" />
</identity>
</endpoint>
<endpoint
address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange"
>
</endpoint>
</service>
</services>
</system.serviceModel>
What am I doing wrong and how can I get this to work over HTTPS? I'm frustrated that this is not as simple as it should be. I have been burried in WCF documentation at MSDN for the months working on this project, and have a good grasp of services, end-points and bindings --- enough to frustrate me even more than if I had no knowledge at all.
UPDATE: Still working on this, I had an odd error when trying to put the full URL for the mex address. I changed to this:
address="https://prcwebs.com/Services/WebPostService.svc/mex"
and got the error:
Security settings for this service require Windows Authentication but
it is not enabled for the IIS application that hosts this service.
I'm not trying to use Windows Authentication, the security setting wasn't changed and is still set to
<security mode="Transport" />
Could not find a base address that matches scheme https for the endpoint with binding WebHttpBinding. Registered base address schemes are [http]
- was not helpful, nothing mentioned that would help
Could not find a base address that matches scheme http for the endpoint with binding WSHttpBinding
- I'm using transport security, this does not apply. tried changing to different security modes, still could not get site to work.
Add multipleSiteBindingsEnabled="true" to the serviceHostingEnvironment and update the security to disable client credentials:
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
EDIT
My final working version under windows 2003 was with the following config.
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
<!-- Set up Custom Behaviors -->
<behaviors>
<endpointBehaviors>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="WebPostService.WebPostServiceBehavior">
<serviceMetadata httpsGetEnabled="true" httpsGetUrl="WebPostServices.svc/mex" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<!-- Set up the binding configuration -->
<bindings>
<wsHttpBinding>
<binding name="SOAPBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="WebPostService.WebPostServiceBehavior"
name="WcfService2.Service1">
<host>
<baseAddresses>
<add baseAddress="https://localhost/Service/Service1.svc"/>
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="SOAPBinding"
contract="WcfService2.IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange">
</endpoint>
</service>
</services>
</system.serviceModel>
You can access the website with https so I guess the certificate part of the installation is correct. If you have anything you want to compare with my setup, let me know.
You are using the wrong bindings for HTTPS.
There is two separate binding classes. wsHttpBinding and wsHttpsBinding notice the s.
You need to add a wsHttpsBinding for HTTPS under bindings and you need a new endpoint for that binding.
Also the particular error you are seeing typically I get to see if IIS hasn't been setup for https from that location.
Open IIS Manager
Open Sites
Right click on Default Web Site.
Edit Bindings
Ensure that there is an entry for https as well as http.
Open IIS Manager
Find your application (I think its going to be Default Web Site).
Right click
Manage Website/Application
Advanced Settings
Enabled Protocols
http,https
I used this and it worked for me, maybe it can help you
To enable the Https on WCF WsHttp bindings, there are some simple steps that should be changed in the web.config file.
Those steps are:
Enable transport level security in the web.config file of the service:
In this step you need to change the security mode from none to Transport. The code below shows how you can do it:
<bindings>
<wsHttpBinding>
<binding name="TransportSecurity">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
Tie up the binding and specify the HTTPS configuration
You need to now associate the bindings, the previews step, with the end points. use the bindingConfiguration tag to specify the binding name. You also need to specify the address where the service is hosted. The code below shows how you can do it
<service name="WCFWSHttps.Service1" behaviorConfiguration="WCFWSHttps.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address=https://localhost/WCFWSHttps/Service1.svc binding="wsHttpBinding" bindingConfiguration="TransportSecurity" contract="WCFWSHttps.IService1"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
.
you also need to change httpGetEnabled to httpsGetEnabled in the serviceMetaData. The code below shows how you can it:
<serviceMetadata httpsGetEnabled="true"/>
Hope it helped
I've used your exact configuration in 3.5 setting and it works with Transport mode using clientCredentialType="None" as mentioned below in Luuk's answer. But just to be sure, I went ahead an created a sample project to simulate as much of your environment as I could gather from the information here.
To simulate your environment I set my IIS (7.5) to use standard Asp.Net 2.0 Integrated app pool. I added 3 http bindings and 3 https bindings in order to simulate your "can have only one address per scheme issue" and baseAddressPrefixFilters works with that.
I only did a search and replace on mysite.com to localhost. Below is the copy paste of exact configuration that I used to produce the screenshot:
web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" />
<authentication mode="None"/>
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<!-- -->
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
<baseAddressPrefixFilters>
<add prefix="https://localhost"/>
<add prefix="http://localhost"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
<!-- Set up Custom Behaviors -->
<behaviors>
<endpointBehaviors/>
<serviceBehaviors>
<behavior name="WebPostService.WebPostServiceBehavior">
<serviceMetadata httpsGetEnabled="true" httpsGetUrl="WebPostServices.svc/mex"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<!-- Set up the binding configuration -->
<bindings>
<wsHttpBinding>
<binding name="SOAPBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="WebPostService.WebPostServiceBehavior" name="WebPostService.WebPostService">
<host>
<baseAddresses>
<add baseAddress="https://localhost/Services/WebPostService.svc"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="SOAPBinding" contract="WebPostService.IWebPostService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
</configuration>
Here's the result:
You'll notice that WebPostService.svc appears twice in mex full url. You need to drop httpsGetUrl to be only mex instead of WebPostService.svc/mex (or drop it out altogether, and it still works fine on my side)
If you'd like to discuss this or what could be different between our envinronments besides IIS version, I'm in WPF chat room almost all day (another 5-6 hours).

Custom Domain for Azure Cloud Service with SSL

I'm trying to expose an Azure Cloud Service using https with a custom domain, but I get an error: "The requested service, 'https://mydomain.net/myservice.svc' could not be activated. See the server's diagnostic trace logs for more information."
Regarding the custom domain: I've followed the steps at https://www.windowsazure.com/en-us/develop/net/common-tasks/custom-dns/#header-1 for the second option, "A record": in godaddy's Zone File Manager, I have an A record configured for the "#" host that "Points To" myservice's "Public Virtual IP Address" (as found in the Azure portal). It seems to me that the fact I'm getting "the service could not be activated" means the A record is working, but I'm not certain.
Regarding the https: I've followed the steps at http://www.31a2ba2a-b718-11dc-8314-0800200c9a66.com/2011/06/how-to-get-and-install-ssl-certificate.html. In brief: I purchased a cert from godaddy using a CSR from my dev machine for mydomain.net, completed the CSR on my dev machine using the friendly name mydomain.net, exported it to mydomain.net.pfx, using that file, uploaded the cert to my cloud service in Azure and configured my WebRole in VS with the cert, and published the web role project to Azure.
On the client side (WP7):
<bindings>
<basicHttpBinding>
<binding name="BasicHttpsBinding_IMyInterface"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint name="BasicHttpsBinding_IMyInterface"
address="https://mydomain.net/myservice.svc"
contract="MyService.IMyInterface"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpsBinding_IMyInterface" />
</client>
Note: I didn't use CName because my cert isn't for a subdomain and it isn't a wildcard.
From my searches, I get the impression this is working for other folks and I can't figure out what I'm doing differently.
yep - you need a matching endpoint specified in the server config. The following is a complete example of a web.config file for a WCF service using HTTP transport security (from http://msdn.microsoft.com/en-us/library/hh556232.aspx):
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="MySecureWCFService.Service1">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="MySecureWCFService.IService1"/>
<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>
<!-- 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="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>

Equivalent web.config settings for WebServiceHostFactory

I'm having problems finding how to setup my web.config to use the same settings as using the WebServiceHostFactory on my RESTful WCF service. Does anyone know what the equivalent web.config would look like instead of using that factory, or how I can find it (assume I should be able to attach and find the endpoint objects etc?).
I need to change a couple of small things that the factory is using, and set the authentication to none, so it will play nicely with IIS (currently getting IIS specified authentication schemes 'IntegratedWindowsAuthentication, Anonymous' - and I cant change the IIS settings).
You should be able to add a reference to your service in the Web.config under the system.serviceModel section.
By specifying the full name of the service implementation as the name, of the service element you can then configure it to use specific end points and behaviours.
Hope this helps.
I have used a similar config to below for controlling my WCF Rest Services.
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
<protocolMapping>
<add scheme="http" binding="httpBehavior"/>
</protocolMapping>
<bindings>
<webHttpBinding>
<binding name="serviceBinding">
<security mode="Transport" />
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="httpBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="{fullname of your service}">
<endpoint address="" behaviorConfiguration="httpCommerceBehavior" binding="webHttpBinding" bindingConfiguration="serviceBinding" contract="{Service Contract full name}>
</endpoint>
</service>
</services>
</system.serviceModel>

WCF service problem with SSL

I have problem with call WCf service over SSL from console app. WCF service is on Windows Server 2003. It's simple math service. The WCF service and client are on the same computer. It's test, I call service on localhost.
web.confing
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="Service.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior">
<endpoint address="https://machineName/https/calculatorservice.svc" name="myEndpoint" binding="basicHttpBinding"
bindingConfiguration="Binding1" contract="Service.ICalculator"/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="Binding1">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpsGetEnabled="true"
httpsGetUrl="https://machineName/https/calculatorservice.svc" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.web>
<compilation debug="true"/></system.web></configuration>
If I call service from Visual Studio examaple : http://localhost:2039/CalculatorService.svc
I get error :
The protocol 'https' is not supported. I think it s ok.
But if I call service from browser I get error :
A registration already exists for URI 'https://machineName/https/CalculatorService.svc'.
What is bad? Can anybody help me, thank you.
Remove the "address" attribute from the endpoint element- when you're hosting in IIS, it automatically supplies this.
Visual Studio Development Server does not support https. You need to host your service in IIS
http://msdn.microsoft.com/en-us/library/vstudio/aa751792(v=vs.100).aspx