A project team recently asked me if they could use the BizTalk BRE to validate incoming data. I asked what sort of validation we were talking about, and it came down to four areas:
- Setting default values when the incoming fields were empty
- Doing look-ups based on existing data and populating related fields
- Doing concatenation of fields
- Catching any business validation errors and recording them
Before answering “of course it can”, I figured I’d quickly roll up my sleeves and prove that the BRE can do those things fairly easily.
First, I had to get my environment set up. This started with a BizTalk XSD schema to represent the data coming into the BRE. In this scenario, the content is actually metadata about a physical file that arrives into the company.
Notice that I have a “validation errors” record at the bottom with a repeating “error” element.
Next, I have a really simple database table that can be used for lookups. Based on providing a “study” and “product” value (which comes in via the inbound XML), I want to be able to figure out which “investigator” to add to the message.
Next I need a .NET class to perform a few functions that the BRE doesn’t provide for me out of the box. First, I need to be able to concatenate two strings. Yes, it’s ridiculous that I have to write an operation to do this vs. the BRE having something built in. Deal with it.
Next, I need a function that can add nodes to my XML message when validation errors are discovered. After adding references to the Microsoft.RulesEngine.dll and System.Xml, I wrote the following quick-and-dirty code.
I accept a “TypedXmlDocument”, yank out the underlying XmlDocument, grab a pointer to the “ValidationErrors” record, and append a new node containing whatever error message was defined within the BRE.
After GAC-ing that helper DLL, I’m ready to roll. Before building my rules in the BRE, I wanted to establish a friendly vocabulary for my XML nodes, database columns and helper functions. So, I defined a new vocabulary and created definitions for all the “get”, “set” and “function” operations that my rules required.
Setting Default Values
The first requirement was to be able to set default values on nodes. This one’s pretty easy. I just check for either an empty string or null value, and set the default value.
The next requirement was to take values from the inbound message, perform a lookup and fill in an empty node from the message. In the rule below, I say that if the value in the XML message equals a value from the database, and another value also equals a value from the database, then set the XML node (Investigator Name) equal to another column in the database.
What this generates behind the scenes when you execute the rule is this:
So the proper T-SQL is built and executed to grab my lookup value.
There’s no out-of-box string concatenation function in the BRE, so here I use the custom class I built earlier. I want this rule to fire at all times, so my condition is set to something that will always be true (unless math itself starts failing). I take a static file path location and then append the file name of the document coming into my company and turn that whole thing into an absolute path to the file.
Catching and Recording Business Exceptions
The final requirement was to detect business validation errors and record them. So, we can use my custom built function from earlier to create rules that look for business errors and add nodes to the message itself which outline the error details.
Remember that my custom function takes in a “TypedXmlDocument” type, so I pass the document itself into the function by dragging the root node of my schema from the XML Schemas Fact Explorer view into the operation parameter.
So what happens when I pass in a document that flexes all these conditions? I start off with an instance document that only has a few values.
So I should see some default values get set, the “investigator” node set based on database lookups, the “file path” node be populated with the concatenated value, and I should see some errors at the end because nodes like “document sub type” and “site” are empty.
To test this rule set, I’m using the built in rule tester, so I have to pass in a valid XML instance, a database connection, and a fact creator that provides the BRE with an instance of my custom .NET class.
When the rule policy is finished executing, my input XML is changed to this:
You can see that all the rules we built earlier got applied successfully. So yes, you can use the BRE to do some pretty easy-to-maintain business validation. This may not be a fit if you’re dealing with a nightly batch of 25,000 records, but if you are doing a messaging based solution, the BRE can do some nice work for you.