IIS-hosted WCF services on a server with multiple IP’s

Although I’ve done a fair amount with WCF, it’s been mostly around hosting services in end-user applications or in Windows services. Every time I’ve tried to host a WCF service in IIS, things suddenly got very complicated and I seemed to spend a lot of time troubleshooting. Well today, I needed to host a WCF service in IIS and ran across such a problem:

This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.

What does that mean? Well, I know the service just sort of piggy-backs on the port and virtual application of the ASP.NET app, so I assumed that the service would get its address and port from IIS. Well, after some digging around a bit, I found this blog post: http://www.robzelt.com/blog/2007/01/24/WCF+This+Collection+Already+Contains+An+Address+With+Scheme+Http.aspx

The problem occurs when the service is hosted in IIS, and that IIS server has multiple IP addresses assigned. This results in multiple baseAddresses. The answer is to create a custom service host. The blog post above didn’t go into all the detail, so I wanted to write this down (mostly for my own benefit), here.

Web.Config:
<?xml version="1.0"?>
<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
</configuration>

Service (ExampleService) and Contract (IExampleService) – NO CHANGE

CustomServiceHost.cs:
public class CustomServiceHost : ServiceHost

{

    public CustomServiceHost(Type serviceType, params Uri[] baseAddresses)

        : base(serviceType, baseAddresses)

    { }

 

    protected override void ApplyConfiguration()

    {

        base.ApplyConfiguration();

    }

}

CustomServiceHostFactory.cs:
public class CustomServiceHostFactory : ServiceHostFactory

{

    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)

    {

        CustomServiceHost customServiceHost =

            new CustomServiceHost(serviceType, baseAddresses[0]);

        return customServiceHost;

    }

}


ExampleService.svc: 

<%@ ServiceHost Language="C#" Debug="true"

    Factory="SederSoftware.WcfExample.CustomServiceHostFactory"

    Service="SederSoftware.WcfExample.ExampleService" CodeBehind="ExampleService.svc.cs" %>

So to piece this all together… When you invoke the ExampleService.svc, it calls the "Factory" specified – CustomerServiceHostFactory. That factory attempts to start a service host – and it specifies just ONE of the IP addresses. Arguably, you could add some logic here to filter which one/ones you want to run from, but for my purposes, just pulling the first one is fine.

From that point on, the rest is like a regular WCF service. So there – you’re welcome, Future Robert, who is not going to remember this in a couple of weeks! Also, the problem I worked with today was with VS2005 and .NET 3.0 – and I just tried this now with .NET 4.0 and it works fine for both.

Posted in Uncategorized, WCF

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
Categories

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 5 other followers

%d bloggers like this: