BizTalk: Validating XML messages in BizTalk 2006

 

XML messages can be validated at different places in BizTalk. Validating at end points using web services (SOAP Adapters), validating using pipeline components (XML Disassembler, XML Validator or custom pipeline components) or validating in an orchestration using custom .NET code (XMLReader class). Default pipeline components provide schema validation and data validation but sometimes you would have to write your own custom pipeline component that can consolidate all the errors instead of throwing exception on the first occurrence of an error. Also you could add additional functionality where you could include the body of the incoming message that was invalid as part of the errors schema or provide options (properties of the pipeline component) to omit the source message body or suspend the message to be monitored in administration console.

sample code that can be called from orchestration and that consolidates all the validation errors is provided below for reference (courtesy: Mike Benage):

[Serializable()]
    public class XmlValidator
    {
        List<string> errorList = null;

        public XmlValidator()
        {
            errorList = new List<string>();
        }

        public void ValidateDocument(System.Xml.XmlDocument businessDocument, string schemaStrongName)
        {

            // Constants
            const int PARTS_IN_SCHEMA_STRONG_NAME = 2;
            const int PART_CLASS_NAME = 0;
            const int PART_QUALIFIED_ASSEMBLY_NAME = 1;

            string instanceId = System.Guid.NewGuid().ToString();
            string[] assemblyNameParts;
            string className;
            string fullyQualifiedAssemblyName;
            System.Reflection.Assembly schemaAssembly;
            Type schemaType;
            Microsoft.XLANGs.BaseTypes.SchemaBase btsSchemaCollection;
            XmlReaderSettings readerSettings;
            XmlSchema btsSchema;

            try
            {

                try
                {
                    // Parse schema strong name
                    assemblyNameParts = schemaStrongName.Split(new char[] { ‘,’ }, PARTS_IN_SCHEMA_STRONG_NAME);
                    className = assemblyNameParts[PART_CLASS_NAME].Trim();
                    fullyQualifiedAssemblyName = assemblyNameParts[PART_QUALIFIED_ASSEMBLY_NAME].Trim();
                }
                catch (Exception ex)
                {
                    throw new Exception("Error loading variables: " + logErrorMessages(ex));
                }

                try
                {
                    // Load assembly
                    schemaAssembly = System.Reflection.Assembly.Load(fullyQualifiedAssemblyName);

                    // Create instance of the BTS schema in order to get to the actual schemas
                    schemaType = schemaAssembly.GetType(className);
                    btsSchemaCollection = (Microsoft.XLANGs.BaseTypes.SchemaBase)Activator.CreateInstance(schemaType);
                    btsSchema = btsSchemaCollection.Schema;
                }
                catch (Exception ex)
                {
                    throw new Exception("Error loading schema: " + logErrorMessages(ex));
                }
                XmlReader reader = null;
                try
                {
                    // Set up XML validating reader and validate document
                    readerSettings = new XmlReaderSettings();
                    int count = 0;
                    string errorMessage = "";
                    readerSettings.ValidationType = ValidationType.Schema;
                    readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
                    readerSettings.ValidationFlags |= XmlSchemaValidationFlags.AllowXmlAttributes;
                    //settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
                    readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessIdentityConstraints;
                    //settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
                    XmlSchemaSet xmlSchemaSet = new XmlSchemaSet();
                    xmlSchemaSet.Add(btsSchema);
                    readerSettings.Schemas = xmlSchemaSet;
                    readerSettings.ValidationEventHandler += new System.Xml.Schema.ValidationEventHandler(reader_ValidationEventHandler);
                    System.Threading.Thread.Sleep(100);
                    using (XmlReader reader = XmlReader.Create(new StringReader(businessDocument.OuterXml), readerSettings))
                    {
                        if (reader != null)
                        {
                            while (reader.Read())
                            {

                            }
                            reader.Close();
                        }
                    }

                }
                catch (Exception ex)
                {
                    throw new Exception("Error validating the document: ");
                }
 

                if (errorList.Count > 0)
                {
                    StringBuilder errorMessage = new StringBuilder("XML Validation failed:" + System.Environment.NewLine);
                    foreach (string error in errorList)
                    {
                        errorMessage.Append("     ");
                        errorMessage.Append(error);
                        errorMessage.Append(System.Environment.NewLine);
                    }
                    throw new Exception(errorMessage.ToString() + System.Environment.NewLine);
                }
            }
            catch (Exception exc)
            {
                schemaAssembly = null;
                schemaType = null;
                btsSchemaCollection = null;
                readerSettings = null;

                throw exc;
            }
        }

        void reader_ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs e)
        {
            errorList.Add(e.Message);
        }

    }

 

 

Related articles:

http://www.digitaldeposit.net/blog/2008/04/extended-xmlvalidation-pipeline.html (uses some obsolete classes in .NET 2.0 but still works with compiler warnings)

http://blogs.msdn.com/scottwoo/archive/2004/08/20/217946.aspx#218167 (does not consolidate all the errors but provides additional properties on the pipeline component to omit the message body or suspend the message)

We ran into some threading issues with custom code called from an orchestration due to the methods that are not thread-safe. With custom pipeline components the thread issues do not exist.

About these ads
This entry was posted in BizTalk. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s