I intend to cover some more foundational material for
BizTalk 2004 in the future, but today I wanted to cover an issue that at
least some people will run into fairly quickly when beginning to use the
product.
There are times when it is desirable to work with multiple XML schemas that
specify the same target namespace, and which specify different definitions for
the same element.
For instance, you may wish to have a lax schema when a document lands on your
doorstep initially - but further into the processing of that document (along a
particular path) you may wish to validate against a stricter schema. Or,
you may have a situation where you have what is arguably an envelope structure
which can't be cleanly stripped off (for a variety of reasons) - leaving you
with documents which might look quite different, but have the same target
namespace and element usage.
BizTalk 2004, in general, wants to see one schema deployed to the BizTalk
management database for any given combination of target namespace and element
declaration. If you deploy two schemas with target namespace
http://MyNamespace and element declaration MyRoot, and then attempt to receive
a MyRoot-rooted document through a receive port using the default Xml Receive
pipeline, you will receive an error from BizTalk like this one:
There was a failure executing the receive pipeline…Source:"XML
Disassembler"…
Reason: The disassembler cannot retrieve the document specification using this
type: "http://MyNamespace#MyRoot". Either the schema is not deployed correctly,
or more than one schema is deployed for the same message type.
To overcome this, you can use custom BizTalk Pipelines on the send and receive
ports that will be dealing with schemas that are subject to the
ambiguity. Within a pipeline, you can restrict the set of available
schemas from "everything that is deployed" down to the schema(s) that you are
interested in.
Specifically, for receive ports, you can add a new item to your project (a
"Receive Pipeline"), and add the default Disassembler and Party Resolution
pipeline components. For the Disassembler component, edit the "Document
Schemas" collection and add the particular schema you are interested in.
See this picture for an illustration.
Likewise, for send ports, you can add a "Send Pipeline" item to your project,
and add the default Assembler pipeline component. Again, specify the
schema you are interested in with the "Document Schemas" collection of the
Assembler.
For each of the Send or Receive ports that will be trafficking in these
messages, specify your newly created pipelines - instead of the default Xml
Receive/Send pipelines!
Now for the gotchya! (you knew there had to be one, right?)
BizTalk 2004 will require that the assembly containing your custom pipeline(s)
is deployed to the GAC (along with every other BizTalk project assembly.)
When components loaded from the GAC wish to dynamically load other types &
assemblies, they must do so with fully qualified assembly names. Applying
this to our current discussion means this: BizTalk pipelines must have fully
qualified information for the assembly that contains the schemas you configure
within pipeline components.
If the pipeline component lives in the same BizTalk project as the schemas you
are attempting to reference, the property designer (when editing the "Document
Schemas" collection) will only be populated with a namespace-qualified type
name - the fully qualified assembly name will be missing. At run time,
the schemas will not be found…and the behavior at run time will appear
completely unchanged from the case where no custom pipeline was specified at
all.
To work around this, simply put your pipelines in a different
project/assembly than the project containing the schemas you need to reference
in the designer.
A bug you say? Certainly it would be nice if the designer warned
you, and it deserves a KB article soon…But keep in mind what is
happening: A GAC-destined component (a pipeline Disassembler) is
providing designer support which allows you to select another component (a
schema) which will be loaded dynamically at run time...It raises an interesing
problem that goes beyond just BizTalk 2004.
Whenever a component that is destined for the GAC has IDE designer support which
in turn allows you to select a type for a "plug in" component that will be
loaded by the "host" component dynamically at run time (without using
Assembly.LoadFrom semantics) - you will run into this issue. Why?
Because if you select a type from the same project, the fully
qualified name can't be reliably known. After all, the project might not
have been compiled yet, or the fully-qualified name might be set up to change
with each compilation (gasp!) via 1.0.*.* versioning policy. If you use
such a designer to select a type in a distinct assembly, the fully qualified
name can indeed be known -and shame on the component author if the versioning
policy isn't sane.
Of course, being deployed into the GAC raises all kinds of thorny issues, but
this one was a bit subtle...