0

I have a WCF service used by some Silverlight code in our web application. It uses the ASP.NET Routing functionality:

private void RegisterRoutes()
{
    var factory = new WebServiceHostFactory();
    RouteTable.Routes.Add(new ServiceRoute("Service", factory, typeof(ServiceService)));
}

This currently works in our Production environment.

On some other environments, I get the exception

System.InvalidOperationException: Could not find a base address that matches scheme http for the endpoint with binding WebHttpBinding. Registered base address schemes are [https].

I have just deployed the exact same code to our Integration environment and to our Training environment. It works in Integration, but fails in Training. Both environments are running the same version of Windows Server 2008 R2 Enterprise, with the same version of IIS 7.5. Both have the same bindings configured in IIS (ports 443 and 80 on all IP addresses).

I have instrumented the code and can see that when it works, both http and https are being used by the service. When it fails, only https is used. The web.config is identical between the two systems.

I know that, in general, with a service hosted in an IIS application, WCF uses the binding information in IIS. In this case, the ASP.NET routing feature is being used.

How does WCF determine which base addresses to use?


Update: Here's an excerpt of our web.config file:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <diagnostics>
      <endToEndTracing propagateActivity="true" activityTracing="true"
       messageFlowTracing="true" />
    </diagnostics>
    <extensions>
      <behaviorExtensions>
        <add name="silverlightFaults" type="Services.SilverlightFaultBehavior, Services" />
      </behaviorExtensions>
    </extensions>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="SilverlightRESTBehavior">
          <webHttp helpEnabled="false" automaticFormatSelectionEnabled="false" 
                   defaultOutgoingResponseFormat="Json" faultExceptionEnabled="false" />
          <silverlightFaults />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <services>
      <service behaviorConfiguration="ServiceBehavior" name="Services.SpendAnalysisService">
        <endpoint address="" behaviorConfiguration="SilverlightRESTBehavior"
          binding="webHttpBinding" contract="Services.SpendAnalysisService" />
        <host> <!-- Added: not in the original-->
          <baseAddresses>
            <add baseAddress="http://" />
            <add baseAddress="https://" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name="d" helpEnabled="false" defaultOutgoingResponseFormat="Json"
          automaticFormatSelectionEnabled="false" faultExceptionEnabled="false" />
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>
</configuration>

Edit:

Another hint: "SSL Required" was set in IIS in the Training environment, and was cleared in the Integration environment. Clearing it in the Training environment prevents the server-side exception. Now, the WCF logs in both environments show that both http and https addresses are being considered.

The question will now be: why does WCF think it needs http when the request arrives as https?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • Defining separate baseAddresses for HTTP & HTTPS doesn't look right but I can't find anything specific to say that won't work. You might want to compare your config with [this SO question & answer](http://stackoverflow.com/questions/3056730/configuring-wcf-4-with-routing-global-asax-for-both-http-https-endpoints) to ensure the configuration is right. Also, there may be some differences between host headers in IIS between the various environments (to make SSL work). On the client side, there could entries in the hosts file that differ between client environments. – Sixto Saez Oct 09 '12 at 18:20
  • The separate base addresses were an experiment and will be removed, since they didn't solve the problem. There are no host headers specified in the bindings. What you say about hosts files is interesting; can you say how that would matter? Hosts files are used, and I got a feeling they might matter, but don't quite see how. – John Saunders Oct 09 '12 at 20:14
  • On the client side, if the Integration machines had hosts files that were similar to production but the Training environment machines were different then you might see a similar issue. Additionally, hosts files will contain entries to replace the machine home address (127.0.0.1) with something like mySecureDomain.org, still pointing at 127.0.0.1, so the domain in the SSL certificates will still be valid to enable HTTPS. – Sixto Saez Oct 09 '12 at 20:55
  • Thanks. FYI, https is always in the list of schemes. "http" is present in Integration but not in Training. – John Saunders Oct 09 '12 at 21:10
  • Big hint, but not yet an answer: See http://msdn.microsoft.com/en-us/library/system.servicemodel.activation.hostedtransportconfiguration.aspx – John Saunders Oct 09 '12 at 23:28
  • I'd try tracing the actual HTTP traffic. You can add built-in [HTTP listeners](http://msdn.microsoft.com/en-us/library/ty48b824.aspx) to your tracing (may to a separate file if they get "noisy"). I've occasionally had to do this to troubleshoot HTTP authentication issues. Maybe the first exchange in the SSL handshaking process starts over HTTP, just guessing here. – Sixto Saez Oct 10 '12 at 00:23

1 Answers1

0

The answer for this very specific question is simple enough:

The failing sites had IIS bindings for both http and https. However, the "Require SSL" flag under "SSL Settings" in IIS was set. This made sense, as the site is only meant to be accessed via SSL (once the load balancer gets set up properly). This was causing WCF to exclude the http scheme from its search for base addresses. Clearing the "Require SSL" flag solved the problem.

The remaining question is probably a question for Microsoft Support once I get a reproducer created: why in the world is WCF even thinking about http since the entire request and all related requests are coming in over https?

I hope to find a way to rewrite this question a bit more generically, so that the answer can benefit someone else. Right now, I'm tempted to close this question as "Too localized".

John Saunders
  • 160,644
  • 26
  • 247
  • 397