Integrating Integrators – BizTalk, Windows Azure, Windows Workflow, and Beyond

XML Validator - C# code - catching errors problem

BizTalk 2004

This group is for all content related to BizTalk Server 2004. This includes a forum, samples, videos, labs, whitepapers, and tools. Most of the content here also applies to other versions of BizTalk beyond 2004.

XML Validator - C# code - catching errors problem

  • rated by 0 users
  • This post has 10 Replies |
  • 1 Follower
  • Hello, I'm working in a project where one of the requirements is to validate an incoming or outgoing document against the schema, catching the error messages that may appear while failing validation. I looked on the web for answers, and the best I could find is in the following site:

    http://thearchhacker.blogspot.com/2004/09/cool-xsd-validation-function-for.html

    Because I wanted the function to return multiple errors (and not just the first failure) I have modified the code to the following:

    [code:1:42eadef361]
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Xml;
    using System.Xml.Schema;
    using System.Reflection;

    namespace BiztalkUtils
    {
    public class Utils
    {
    static int ErrorsCount = 0;
    static string ErrorMessage = \"\";

    public static void ValidateDocument(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;

    ErrorsCount = 0;
    ErrorMessage = \"\";

    // Parse schema strong name
    string[] assemblyNameParts = schemaStrongName.Split(new char[] { ',' }, PARTS_IN_SCHEMA_STRONG_NAME);
    string className = assemblyNameParts[PART_CLASS_NAME].Trim();
    string fullyQualifiedAssemblyName = assemblyNameParts[PART_QUALIFIED_ASSEMBLY_NAME].Trim();

    // Load assembly
    Assembly schemaAssembly = Assembly.Load(fullyQualifiedAssemblyName);

    // Create instance of the BTS schema in order to get to the actual schemas
    Type schemaType = schemaAssembly.GetType(className);
    Microsoft.XLANGs.BaseTypes.SchemaBase btsSchemaCollection = (Microsoft.XLANGs.BaseTypes.SchemaBase)Activator.CreateInstance(schemaType);

    // Set up XmlVali######Reader and validate document
    XmlParserContext parserContext = new XmlParserContext(null,null, \"\", XmlSpace.None);
    XmlVali######Reader reader = new XmlVali######Reader(businessDocument.OuterXml, XmlNodeType.Document,parserContext);

    reader.ValidationType = ValidationType.Schema;
    reader.Schemas.Add(btsSchemaCollection.SchemaCollection);

    // Set up ValidationEventHandler
    reader.ValidationEventHandler += new ValidationEventHandler(reader_ValidationEventHandler);

    while (reader.Read()) { }

    reader.Close();

    // Throw XmlSchemaException to be caught by BizTalk containing all validation errors
    if (ErrorsCount > 0)
    {
    throw new System.Xml.Schema.XmlSchemaException(ErrorMessage);
    }
    }

    private static void reader_ValidationEventHandler(object sender, ValidationEventArgs e)
    {
    ErrorsCount++;

    //Construct error message
    ErrorMessage = ErrorMessage
    + \"Error #\" + ErrorsCount
    + \" (Line \" + e.Exception.LineNumber
    + \", Pos \" + e.Exception.LinePosition + \"): \"
    + e.Exception.Message
    + System.Environment.NewLine;
    }

    }

    }
    [/code:1:42eadef361]

    Note: Substitute \"######\" in the code with d`a`t`i`n`g (without the \"'\") as the spam blocker would not let me attach the code otherwise.

    This works perfectly when I test my orchestration and validate 1 or a few xml files at a time. However, when I try to validate 100 files at once (50 valid and 50 invalid), I get unpredictable behaviors (the number of files that pass validation is not always 50, and the error messages sometimes get \"mixed up\" between the different messages).

    I am not an expert in C#, but I think there may be something wrong with the class I'm using.

    I also tried putting the call to the validation function inside an Atomic Scope, disabling batching and playing with the other settings, but the different instances that are being run by BizTalk still seem to interfere with each other. As I said, if I validate just one file at a time, everything works perfectly.

    I would REALLY appreciate any comments and help on why this behavior may be occuring. Thanks
  • [... continued from previous... ]

    This works perfectly when I test my orchestration and validate 1 or a few xml files at a time. However, when I try to validate 100 files at once (50 valid and 50 invalid), I get unpredictable behaviors (the number of files that pass validation is not always 50, and the error messages sometimes get \"mixed up\" between the different messages).

    I am not an expert in C#, but I think there may be something wrong with the class I'm using.

    I also tried putting the call to the validation function inside an Atomic Scope, disabling batching and playing with the other settings, but the different instances that are being run by BizTalk still seem to interfere with each other. As I said, if I validate just one file at a time, everything works perfectly.

    I would REALLY appreciate any comments on why this behavior may be occuring. Thanks
  • I think the problem is that the method is Static. I have had problems with that in the past.

    I’m guessing it’s static since it is working with Xml items that are not serilizable even if you marked the class that way.

    First off, I’d make the class an instance class and mark it serilizable to see if that works.

    If not, you might want to try [ThreadStatic] as this will create a new object per thread (I think – never actually tried it).

    If neither of those works, you’ll have to make it non serilizable and an instance object thus calling it inside an Atomic Scope shape.

    Let me know how it goes.

    Stephen W. Thomas
    http://www.BizTalkGurus.com

  • [quote user=\"Stephen W. Thomas\"]
    If not, you might want to try [ThreadStatic] as this will create a new object per thread (I think – never actually tried it).


    I tried the [ThreadStatic] approach and now it seems to be working fine! I will test this a little more to be sure, but thanks for the response!
  • I still need a little help here... I started using the same validation class in a BizTalk 2006 solution. It is still working perfectly, but because the XmlVali######Reader is obsolete in .Net 2.0, I'm getting warnings. I tried modifying the class to use the following code instead of the XmlVali######Reader approach:

    [code:1:144a86be14]
    // Set up XmlVali######Reader and validate document - OBSOLETE!
    //Using XmlReaderSettings instead

    XmlReaderSettings settings = new XmlReaderSettings();

    settings.ValidationType = ValidationType.Schema;

    XmlReader reader = XmlReader.Create(new System.IO.StringReader(businessDocument.OuterXml), settings);
    foreach (XmlSchema xschema in btsSchemaCollection.SchemaCollection)
    {
    settings.Schemas.Add(xschema);
    }

    settings.ValidationEventHandler += new ValidationEventHandler(reader_ValidationEventHandler);

    while (reader.Read()) { }

    reader.Close();[/code:1:144a86be14]

    However this is not getting my document validated at all (it always validates fine even when it shouldn't). Any idea on what could I be missing? Thanks again for the help
  • nothing man.

    Edit
  •  

     

     

     

     

    Just need to add some of theese validation flags.

    settings.ValidationType =

     

    ValidationType

    .Schema;

    settings.ValidationFlags |=

     

    XmlSchemaValidationFlags

    .ProcessInlineSchema;

     

     

    //settings.ValidationFlags |= XmlSchemaValidationFlags.AllowXmlAttributes;

    settings.ValidationFlags |=

     

    XmlSchemaValidationFlags

    .ProcessSchemaLocation;

    settings.ValidationFlags |=

     

    XmlSchemaValidationFlags

    .ProcessIdentityConstraints;

    settings.ValidationFlags |=

     

    XmlSchemaValidationFlags

    .ReportValidationWarnings;

    Edit
  • Rather than calling xmlReader.Close, wrap use of the xmlReader in a using statement:

                using(XmlReader reader = XmlReader.Create(xpathNavigator.ReadSubtree(), settings))
                {
                    while (reader.Read()) {}
                }

  • Hello

     

    I have a problem to catch the System.Xml.Schema.XmlSchemaException in the orchestration.

    Exception Object Type = System.Xml.Schema.XmlSchemaException

    it works only with the Exception Object Type = System.Exception

     

     

     

  • all exception handling can be done in the scope!! even schema exception handling also!!

    Edit
  • Hi,i had same issue with similar code while load testing with 100 + messages .Can you please help me out on that the way you solved?

    Edit
  • Page 1 of 1 (11 items)