10

My employers website has multiple hostnames that all hit the same server and we just show different skins for branding purposes.

Unfortunately WCF doesn't seem to work well in this situation.

I've tried overriding the default host with a custom host factory.

That's not an acceptable solution because it needs to work from all hosts, not just 1.

I've also looked at this blog post but either I couldn't get it to work or it wasn't meant to solve my problem.

The error I'm getting is "This collection already contains an address with scheme http"

There's got to be a way to configure this, please help :)

Ryu
  • 8,641
  • 10
  • 65
  • 98
  • Are you hosting your WCF with IIS or are you building a custom hosting provider? – thaBadDawg Jan 07 '09 at 22:33
  • Also, what is the specific issue/problem you have? I.e. does the service not function, returns incorrect responses (URLs) or is it that the service is unaware of which client is making the call? – Bernhard Hofmann Jan 07 '09 at 22:51
  • This collection already contains an address with scheme http – Ryu Jan 12 '09 at 15:09

5 Answers5

5

I don't think that the host base addresses solution posted above will work for IIS-hosted websites (the OP did mention that this was for his employer's website).

See this blog post

Also, the other answer further up by thaBadDawg won't work where multiple host headers are specified - you'll just get the errors that the OP mentions ("This collection already contains an address with scheme http".)

I don't think any of the solutions mentioned so far will work, because it doesn't look like WCF allows a single service to be accessible for a single site with multiple host headers from all of the sites. The only workaround I could find for .Net 3.5 (and under) is to create a different contract for each of the host headers, and use the custom ServiceHostFactory to use the correct host header based on which contract is specified. This isn't at all practical. Apparently .Net 4.0 will resolve this issue.

zcrar70
  • 3,158
  • 2
  • 24
  • 18
  • The other workaround is the one mentioned by **struhtanov**. Basically all you need to do is create different endpoint for each host (don't have to change the contract). – chenz Sep 06 '11 at 02:07
5

If you don't put an address in the endpoint then it should resolve to whatever server hits the service. I use this code and it resolves both to my .local address and to my .com address from IIS.

<system.serviceModel>
    <services>
        <service name="ServiceName" behaviorConfiguration="ServiceName.Service1Behavior">
            <endpoint address="" binding="wsHttpBinding" contract="iServiceName">
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="ServiceName.Service1Behavior">
                <!-- 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>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>
thaBadDawg
  • 5,160
  • 6
  • 35
  • 44
  • does this scenario work when you have multiple host headers? it looks like it doesn't work for me (ASP.NET 3.5 / IIS 6). zcrar70's post seems to agree. – russau Aug 25 '10 at 03:02
3

I met this problem several days ago. Actually I have the same situation that Ryu described originally in his question. We have one virtual directory for many customers but each of them has his own binding. Like "http://company1.product.com", "http://company2.product.com" etc.

Solution described here works. But what is the price! We should change web.config each time when we need to add new binding. And also web.config should contain absolute path prefix like <add prefix=”http://company1.product.com”/>.

It is possible to bypass first problem. I wrote my own CustomHostFactory for WCF service, where I dynamically add endpoints. And this endpoints I retrieve from IIS bindings(there is a way to get information from IIS).

Here is sample code :

protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
    var serviceHost = base.CreateServiceHost(serviceType, baseAddresses);
    var webHttpBinding = new WebHttpBinding();
    var serviceEndpoint1 = serviceHost.AddServiceEndpoint(typeof(IService), webHttpBinding,
                                                         "http://company2.product.com/WCFService/Service.svc");

    var serviceEndpoint2 = serviceHost.AddServiceEndpoint(typeof(IService), webHttpBinding,
                                                 "http://company1.product.com/WCFService/Service.svc");

    var webHttpBehavior = new WebHttpBehavior();

    serviceEndpoint1.Behaviors.Add(webHttpBehavior);
    serviceEndpoint2.Behaviors.Add(webHttpBehavior);

    return serviceHost;
}

And instead of hardcoding endpoint urls, you sould retrieve them from IIS. But ServiceHost is created once when application starts. So if you need to add new binding, you should restart IIS. It is not a solution for us.

That is why we decided to move to asmx (like is described here). And wait until Framework 4.0 release, where multiple bindings should be supported.

struhtanov
  • 416
  • 2
  • 10
  • With .NET 4.0 you don't need to specify all host headers in config anymore, just add `` as decribed in Rampo's blog. Thanks for the link. – Jan Zahradník Aug 13 '14 at 10:45
0

A simple workaround that doesn't involve any code or config changes is to create yet another website in IIS which points to the same physical directory, and the same app pool, but with a different host-header binding. This can be done for as many different host names as you have.

LMK
  • 1,496
  • 1
  • 13
  • 15
-1

I'm sure you've figured it out by now, but just for fun I'll post here anyway.

I've had this exact problem and spent forever trying to figure it out. The best solution is to put the host base addresses in your service definition, which allows the service to operate under these multiple addresses. For this solution to work, you still need the ServiceHostFactory to be overridden. Since you've already done that, just leave it in there.

<service behaviorConfiguration="ServiceBehaviour" name="Api.Service">
    <endpoint address="soap" binding="basicHttpBinding" contract="Api.IService" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="http://host1.com/Api" />
        <add baseAddress="http://host2.com/Api" />
      </baseAddresses>
    </host>
  </service>
Steve
  • 939
  • 1
  • 9
  • 18
  • 2
    baseAddresses is ignored in IIS. ("This is completely ignored when hosting in IIS" http://msdn.microsoft.com/en-us/library/ms788995.aspx) – russau Aug 25 '10 at 03:07
  • unfortunately this did not work for me either...still searching for a solution. – Tone Jul 14 '12 at 05:20