12/22/10

Use Preprocessor Directives to Support Multiple Web Service Versions

When there is a new version of a web service in a different URI, we usually just need to point to that new URl and get the new reference class for that service. A problem may arise when the new service definition does not keep backward compatibility, and your project will no longer compile because a property or method was either renamed, or it no longer exists.
An approach to address this problem is to create an assembly that provides a facade to abstract the object model of the web service.  In this facade, you can use preprocessor directives to indicate what web service namespace to include and what code to compile. This is a simple scenario:

Version 1
Version 2
namespace mydomain.services.version1 {
   
  public partial class myclass {
     public string LName;
     ....
  }
}
namespace mydomain.services.version2 {
   
  public partial class myclass {
     public string LastName;
     ....
  }
}


In this scenario,  the namespace and a property have changed. If you try to compile the code that consumes the web service using version two, there will be compilation errors because the namespace does not exists, and there is no LName property. You will then need to change the code to match the new web service definition, and all should work fine. But, what if you need to support both web service versions for different product releases? In this case, you may want to have the implementation for both versions in the same codebase. To achieve this, you can write the following on the facade class:
#if USE_VERSION2
using mydomain.services.version2;
#else
using mydomain.services.version1;
#endif
On the project conditional compilation symbols,you can add USE_VERSION2 as the symbol to indicate what code segment should be included. In this case, version2 wil be used. If not compilation symbol is added, the default will be version1.
To address class members backward compatibility like in the case of the LastName property change, you write a facade property as follows:
public string LastName
{
#if USE_VERSION2
    get {return service1.LastName;}
#else
    get {return service1.LName;}
#endif        
}
The property provides access to the member of the selected version. In this case, LastName when using version2 or LName as the default.
With this approach, the client that consumes the facade is abtsracted from the web service object model. Support to additional versions is done in the facade thus minimizing the impact to the rest of the application.
I hope you find this useful.


og-bit.com