tags:

views:

2203

answers:

5

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 :)

+4  A: 

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
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
A: 

Apparently there's something new in framework 3.5 that addresses exactly this.

Msdn

Here's an article that covers this in more depth.

towps
That doesn't solve the problem. Only allows you to live with the problem: only one hostname allowed per service.
graffic
A: 

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
baseAddresses is ignored in IIS. ("This is completely ignored when hosting in IIS" http://msdn.microsoft.com/en-us/library/ms788995.aspx)
russau
+2  A: 

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
A: 

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”/&gt;.

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.

Sergey