Duplicate Namespace Issue with Schema Validation in Pipeline Components
July 29, 2013 5 Comments
Today I was tasked with enabling XML schema validation for an existing WCF receive location in BizTalk. The client was already using the out-of-the-box XmlReceive pipeline, so I figured this would be short work, finished by lunchtime after all the regression tests had been run. Little did I suspect that I would run into a snag that would enlighten me to a new BizTalk “feature”.
Because of a compressed time schedule, we wanted to avoid having to add a new custom pipeline to the solution, even one as simple as containing a standard XmlValidator component. So instead, I opted to use port-based configuration by enabling validation within the XmlDissembler component in the existing XmlReceive pipeline. Of course, this does require specifying the list of specific schemas in the DocumentSpecNames property on the port instance:
The trick here, of course, is to ensure you get these specifications correct, as they need to be fully qualified assembly (FQN) references. Moreover, if you are expecting multiple message types, you need to separate the entries with a pipeline (“|”) delimiter, something not so obvious if you don’t read the Microsoft documentation. Even less obvious is how to deal with multipart schemas that contain multiple root nodes (at least this blog post sheds some light there).
This client was indeed expecting multiple message types, so I sourced the FQN’s by finding the deployed schemas in the Schemas node under the application in the BizTalk Admin Console (use a comma to separate the .NET schema name from the assembly name):
Confident that I had the list correct, I was surprised to keep getting the following error during testing:
There was a failure executing the receive pipeline: “Microsoft.BizTalk.DefaultPipelines.XMLReceive, Microsoft.BizTalk.DefaultPipelines, Version=126.96.36.199, Culture=neutral, PublicKeyToken=31bf3856ad364e35” Source: “XML disassembler” Receive Port: “XmlValidationReceivePort” URI: “C:\BizTalk\Folders\XML_VAL_IN\*.xml” Reason: The document failed to validate because of the following error:”The ‘http://XmlValidationTest.CommonNamespace:Schema1′ element is not declared.” .
How can it say that the root node name is not declared when clearly it is a recognised message type in BizTalk??
Interestingly, when I removed either one of the two schemas from the list, it worked fine in both cases! Surely I didn’t get the delimiter wrong? To prove this, I added third schema to the list, and it still worked – but only if just one of the two original schemas was specified.
Looking more closely, I realised that these two schemas shared the same target namespace – even though their root nodes (and consequently, BTS.MessageType) was different. So I decided to see what was happening under the covers by creating a custom pipeline version of what I was doing in the port, i.e. adding an XmlDisassembler component in the Visual Studio Pipeline Designer and using the picker to select the two schemas in the Document Schemas property. This enabled me to inspect the XML generated by the component within the pipeline:
What do you know… there’s this hidden DocumentSpecTargetNamespaces property which (oddly enough) lists all the target namespaces that go with the schemas specified in the DocumentSpecNames property! I don’t know exactly what the BizTalk engine does with this property (I would welcome any enlightening comments from those more knowledgeable than I about this), but I was willing to bet that having the same target namespace specified twice was going to cause some confusion.
To prove this, I changed the target namespace in one of the schemas and lo & behold – it all worked fine! Now I was not only avoiding the previous error, but got the expected error messages for both invalid message formats and unrecognised messages:
There was a failure executing the receive pipeline: “Microsoft.BizTalk.DefaultPipelines.XMLReceive, Microsoft.BizTalk.DefaultPipelines, Version=188.8.131.52, Culture=neutral, PublicKeyToken=31bf3856ad364e35” Source: “Pipeline ” Receive Port: “XmlValidationReceivePort” URI: “C:\BizTalk\Folders\XML_VAL_IN\*.xml” Reason: The document failed to validate because of the following error:”The element ‘Schema2’ in namespace ‘http://XmlValidationTest.CommonNamespace2′ has invalid child element ‘UnexpectedElement’. List of possible elements expected: ‘Element2’.” .
There was a failure executing the receive pipeline: “Microsoft.BizTalk.DefaultPipelines.XMLReceive, Microsoft.BizTalk.DefaultPipelines, Version=184.108.40.206, Culture=neutral, PublicKeyToken=31bf3856ad364e35” Source: “XML disassembler” Receive Port: “XmlValidationReceivePort” URI: “C:\BizTalk\Folders\XML_VAL_IN\*.xml” Reason: No Disassemble stage components can recognize the data.
The next step would be to confirm if using the XmlValidator component instead would yield the same results…and this yielded some very interesting results. I changed the custom pipeline in the Pipeline Designer to remove the schema validation in the XmlDisassembler component, and added an XmlValidator instead. The good thing about this component is that it does not require a list of schemas to be specified in the DocumentSpecNames property (unless you want to limit the allowed message types) – if left blank it will automatically validate against any matching schema found in the database.
I discovered that when you did not populate the DocumentSpecNames property, everything worked fine. It correctly validated any message submitted as long as it could find a matching schema deployed in the database, even if there were multiple schemas sharing the same namespace. Hooray!
However, looking at the XML behind the pipeline, I noticed that it too uses the hidden DocumentSpecTargetNamespaces property. So I tried adding my document specification list:
XmlValidationTest.Schema1,XmlValidationTest, Version=220.127.116.11, Culture=neutral, PublicKeyToken=5751c30f9b49b7bb|XmlValidationTest.Schema2,XmlValidationTest, Version=18.104.22.168, Culture=neutral, PublicKeyToken=5751c30f9b49b7bb
And what do you know… it broke again! Same error as before (“…The ‘http://XmlValidationTest.CommonNamespace:Schema1′ element is not declared.”) Apparently, two listing of the same namespace within the hidden DocumentSpecTargetNamespaces property confuses the engine the same way as it does in the XmlDisassembler component.
So in summary, the lessons learned pertaining to XML schema validation in BizTalk Server are:
- Try to use unique target namespaces when defining your BizTalk message types. Admittedly, you may not always be able to do this when employing schemas from external entities that your organisation does not own.
- If you must validate schemas that use a common namespace, then use an XmlValidator component in a custom receive pipeline (along with an XmlDisassembler, of course) to perform the validation – but ensure that you DO NOT specify any schemas in the DocumentSpecNames property! Note that this pipeline will accept messages of any type that is currently deployed to the BizTalkMgmtDb database.
- In addition, if you need to restrict the message types allowed through the port, then use the DocumentSpecNames property on the XmlDisassembler component to specify the target schemas (without turning validation on in that component). In this way, the disassembler will filter the message types whilst the validator will correctly perform its function on the types that are allowed through the disassembler. See the example configuration below: