March 12, 2004

Namespaces

In .NET parlance, WSE is a Library, not a Platform. The primary distinguishing characteristic is that between WSE major versions there can be breaking API changes, breaking wire-format changes and there is no guarantee of backward compatibility. Just because WSE 1.0 has a class called Microsoft.Web.Services.SoapContext doesn't guarantee that WSE 2.0 will have that class, that it will have the same interface or that methods with the same name will have the same behaviour.

Given this, how do you deal with the adoption of WSE versions over time? Can different versions co-exist on the same machine? What about the same AppDomain? What happens when that application you built 6 months ago with WSE 1.0 needs to talk to a second service that is built with WSE 2.0? How do you host the same service accessible using different versions of WSE? These are some of the questions we've been investigating as part of our Application Building exercises as we get closer to the release of WSE 2.0.

We had always planned for Side-by-Side existence of different major versions of WSE on the same machine. This is why we moved away from placing configuration data in the machine.config file and instead pushed the model of declaring the WSE config section handler inside an applications config file. However, hosting different versions of WSE inside a single AppDomain takes things a step further. Are there any runtime conflicts? Can you reference both assemblies in the same Visual Studio project? How do you have a single source file that uses classes from both versions?

Hosting both versions in a single AppDomain turned out to be relatively trivial from a technical perspective: there are a couple of conflicts including the configuration section name, trace file names and so on, but our use of other resources such as Thread Local Storage or X509 Certificate Stores were non-issues. Where things got tricky was the user experience.

Visual Studio presently does not allow you to reference two assemblies with the same file name (but different strong names) in the same project. To make things work, we had to encapsulate the code using different WSE versions into separate projects so that each only referenced a single version of WSE. Whilst this works, and some may prefer it as a matter of design, it's not as simple as we'd like: we're still left with the fact that by re-using the namespace across different versions we may be misleading people into assuming that the classes exhibit the same behaviour or that they can be passed between the different versions.

WSE major versions are not simply incremental feature additions, they are different libraries. As such, they deserve different names. The classes should have different names to reflect the fact that they may have different behaviour. The assemblies should have different names to reflect that they are different. Giving the classes different names (by changing the namespace) and renaming the assemblies also gives new options for developers: now you can reference the two (or more) different assemblies from a single Visual Studio project, even from a single class in that project[1].

As a result of these investigations and a 2 hour find/replace game in an editor, WSE 2.0 is now Microsoft.Web.Services2 and the config section is called <microsoft.web.services2>.

This change allows us to enable the following side-by-side scenarios:

  • Single server application running multiple services, each accepting requests using a different wire format[2].
  • Single machine running multiple server applications, each using a different wire format.
  • Single client application sending requests with different wire formats.
  • Single service accepting requests over one wire format and sending requests using a different wire format.

We will also ensure that the toolsets from different versions of WSE will co-operate with each other when you use multiple versions in the same project.

Scenarios that we are explicitly not supporting are:

  • Single service accepting requests using multiple wire formats - there's no simple way to sniff the messages to determine which version they are using and there are other conflicts from the Soap processing model. The services must have different endpoints.
  • Relay accepting messages over one wire format and translating to another wire format. The WSE 2.0 router will not be able to translate messages to WSE 1.0 wire format; the potential deltas in the wire formats make this difficult. Of course, if the incoming message is signed, such a translation would likely break the signature.
  • We are not supporting sharing class instances between versions. For example, you cannot host a WSE 1.0 SoapFilter inside the WSE 2.0 Pipeline.

For customers using WSE we think this change gives you greater flexibility in developing and deploying your WSE-enabled applications over time. It also crystalises the fact that different versions of WSE are different libraries and need to be considered as such.

[1]This gets even easier with the Whidbey version of the .NET Framework.

[2]This scenario is not supported if the services are written using ASMX; it is supported for WSE's own Messaging stack. We are not enabling co-existence of the multiple SoapExtensions used in the ASMX case for a single AppDomain, you must use different virtual directories for this scenario. Of course, some of you may find ways to make this work.

Posted by herveyw at March 12, 2004 11:38 PM
Comments