Thursday, April 15, 2004
A colleague came to me today with a problem to do with duplicate schemas at runtime when running his orchestrations.
The problem turned out that during generation of the proxy (when adding a web reference to a BizTalk project) to a web service that was automatically generated by the BizTalk Web Services Publishing Wizard, then if the web service exposes a complex type such as a message, then the proxy automatically generates a schema called Reference.xsd that contains a local definition of the message.
However, this may all seem fairly benign on the surface. But, the proxy generator uses the WSDL to create the proxy orchestration (Reference.odx) and the schema (Reference.xsd), and the WSDL was created based on a web service that has been automatically generated by the BizTalk Web Services Publishing Wizard. The WSDL for the web service contains definitions for the messages that are required as parameters to the web service operations, and they are defined in the WSDL with the same root name and namespace as the real schema that they are based on!So, when you compile the orchestration that is consuming the web service, a Reference.xsd schema containing the definitions for the messages expected as parameters to the web service, are compiled into the assembly as well.
This is a big issue, because once both assemblies are deployed (one containing the consumed orchestration that includes the original schema for the message and one containing the orchestration that is calling the web service and includes a proxy generated schema for the message) then at runtime BizTalk will fail because 2 schemas exist in the Management database with the same root element and namespace names!
So, how do we get around this? I can only think of these 2 ways:
- Create a .NET class that wraps the web reference, create a static method that wraps the web service call, and then call the class method from within an Expression shape in orchestration, thereby avoiding creating the web reference inside the BizTalk project.
- Pass the message as a string to the orchestration before running the wizard, but that way you'll need to convert the string back to a message reference within the consuming orchestration.
If anybody else has any other ideas, I'd be interested to hear about them here!