Hosting a WCF Service with ASP.NET Compatibility Enabled Kills my inner child

We host a couple of web services that integration partners connect to. One of the big challenges when hosting these services is ensuring nothing breaks for our integration partners when we upgrade the service with new features. The way we implemented this in WCF was to create a new Service Contract (or interface in C#) for each version that has new operations added to it. Then a single class can implement multiple versions.

Example

using Version1 = MyServiceApp.Version1;
using Version2 = MyServiceApp.Version2;

public class MyServiceClass : Version1.IUsersService, Version2.IUsersService
{
    public void AuthenticateUser(string userName, string password)
    {
        // Act like a V1 and a V2 web service
    }
public void SomeVersion2Method(string someVersion2Param)
{
// Act like a V2 web service
}
}

To ensure that the web service consumers are aware there is a new service we like to host each version at a separate web address. We name each service with the month that implementation for that version began, as this is usually a constant that doesn’t change throughout development, unlike release dates which can be pushed… 😉

Example

Version1 hosted at http://www.ourdomain.com/API/2008/01/UserService.svc 
Version2 hosted at http://www.ourdomain.com/API/2008/06/UserService.svc

So IIS hosts our services in a single Web application and this was fine for our Version1 of the service… until we deployed Version2…

Problem

Every time we access one of the endpoints the other one gives an error resembling:

InvalidOperationException: The address "blah" is already registered:

We tried everything:

1. Explicitly specifying the ListenUri for Version1 gives…

A registration already exists for URI ‘http://www.ourdomain.com/API/2008/01/UsersService.svc’.

But only after accessing the Version2 service first, then accessing Version1 crashes, if you access Version1 then Version2 crashes.. ARGGH!!!

2. Explicitly specifying the Address for Version 1 and Version 2… Same thing…

3. Explicitly specifying the Address and ListenUri for Version 1 and Version 2… Same thing again…

I was stumped until I noticed that the web.config had this in it:

<serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> 

"This couldn’t have anything to do with it… surely" I thought to myself… Sure enough, turn this off and viola! The same service can be hosted from two separate endpoints (or addresses) with both endpoints supporting both contracts, and the Config’s needn’t say anything about how to do it. This makes it easy for us to ensure backwards compatibility while making it clear to any developer what the latest version of the service contract is… Huzzah!.

Final Web.config

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
    <services>
        <service name="MyServiceApp.MyServiceClass"
                 behaviorConfiguration="StandardServiceBehavior">
            <endpoint name="SecureEndpoint"
                      binding="basicHttpBinding"
                      bindingConfiguration="AnonymousSecure"
                      bindingName="AnonymousSecure"
                      bindingNamespace="http://www.ourdomain.com/API/2008/01"
                      contract="MyServiceApp.Version1.IUsersService"
                  />
            <endpoint name="SecureEndpointVersion2"
                      binding="basicHttpBinding"
                      bindingConfiguration="AnonymousSecure"
                      bindingName="AnonymousSecure"
                      bindingNamespace="http://www.ourdomain.com/API/2008/06"
                      contract="MyServiceApp.Version2.IUsersService" />
        </service>
    </services>
    <bindings>
        <basicHttpBinding>
            <binding name="AnonymousSecure" maxReceivedMessageSize="10000000">
                <security mode="Transport">
                    <transport clientCredentialType="None" proxyCredentialType="None"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
...
</system.serviceModel>

Advertisements
  1. #1 by Hugh on September 19, 2008 - 9:31 pm

    Thanks for that – saved me hours or even days of googling and frustration.  I have 4 endpoints on one service and couldn\’t figure out why it worked in development but not in release.
     

  2. #2 by khaled on November 10, 2009 - 8:34 pm

    thank you please can you send to me sample i try it by i cannot workkhaled mohamed

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

%d bloggers like this: