Had a problem with WCF that I thought I should blog about.
We're in the scenario where we have a WCF service that needs to call another service to do some calculating and then return the result back to the client. For now, the service is hosted on the same server, but eventually, it could get expensive, so we'll push out that calculation to another server.
The WCF configuration also has an endpoint address that is not the same as the base address reported to it by IIS; IIS is of course reporting the machine name for the base address. So here's the problem, you'd browse to the service url https://my.url.com/service/service.svc and you'd get the nice service page, but the url for the WSDL would be wrong, it'd be https://servername.anotherurl.com/service/service.svc?wsdl, and when the service would try and call the first url, you'd get weird 404 File Not Found errors, even though you could browse to the service and it'd work fine!
Turns out the 404 error was somewhat of a bad error. The file was being found, but the XSD's that were generated were not, because they were at the wrong url. If you clicked on the wsdl location, you'd see urls for https://servername.anotherurl.com/service/service.svc?xsd=xsd0 or something like that.
To make matters worse, the ssl certificate didn't match the servername url, which caused problems. I didn't discover this until I tried to run svcutil on the service and came up with:
Attempting to download metadata from 'https://my.url.com/service/service.svc?wsdl' using WS-Metadata Exchange or DISCO.
Microsoft (R) Service Model Metadata Tool
[Microsoft (R) Windows (R) Communication Foundation, Version 3.0.4506.648]
Copyright (c) Microsoft Corporation. All rights reserved.
Error: Cannot obtain Metadata from https://my.url.com/service/service.svc?wsdl
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
Metadata contains a reference that cannot be resolved: 'https://my.url.com/service/service.svc?wsdl'.
There was no endpoint listening at https://my.url.com/service/service.svc?wsdl that could accept the message. This is often
caused by an incorrect address or SOAP action. See InnerException, if present,
for more details.
The remote server returned an error: (404) Not Found.
HTTP GET Error
The document was understood, but it could not be processed.
- The WSDL document contains links that could not be resolved.
- There was an error downloading 'https://servername.anotherurl.com/service/service.svc?xsd=xsd0'.
- 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.
After digging forever, I went down the path of seeing if I could modify the base address. Nope, that failed, IIS provides the base address and what you set in the config is ignored. So I tried modifying the behavior to have a specific behavior for this service. That fails, because the URL is then created twice and you'll get an error. Finally, I discovered that you can indeed use host headers on ssl!
Following the instructions here, I set the host header and after restarting IIS, the service page displayed the right urls, and the service worked like a charm. You can get the service ID from IIS by clicking the Web Sites folder. Also, the adsutil script is in the AdminScripts folder under inetpub.
I also discovered that you can't have more than one host header for IIS or wcf will break. Bummer. You can fix it with an article by Rob Zelt. I don't like how he arbitrarily picks a host header; that seems rather fragile. I'd instead read the base address out of a config file and then iterate through until I found the one that matched (or even just set it without using the passed in host headers at all).
Anyway, now I know!
Update (7/7/08): You also need to not have a value for the endpoint address. Not sure why, but that seems to make it work.
Technorati Tags: WCF