Tech Blog

Distinguished Fields and Optional Elements

Thought this might be of interest to a few BizTalk developers out there.

It’s quite common practice to use Distinguished Fields in orchestrations, to get/set
the value of an element or attribute.

However, if the element you’re trying to set/get doesn’t exist, then this poses a
few problems.

Setting a Distinguished Field

If the element/attribute doesn’t exist in the target message, then you’ll get an exception,
no questions asked – there’s no way around this.
Under the covers, the SetDistinguishedField method
is called to set the value – and it doesn’t check if the element/attribute exists
first.
The same thing happens if you use the xpath() function
to set a value, and the element/attribute doesn’t exist – BizTalk isn’t about
to modify your message and add the element/attribute for you.

In this case, it’s your responsibility to check that the element/attribute exists.
If it’s a message that you create, then you have to make sure that the element/attribute
is created (do this in a map by mapping an empty Value Mapping functoid to it, or
setting the Value property to “<empty>“).

Getting a Distinguished Field

This is more interesting.
In a nutshell, if the Distinguished Field is of type string (or
any other nullable type) then you’ll get null.
Otherwise, you’ll get an InvalidCastException.

The reason for this is in the underlying code.

The orchestration calls XSDPart.GetDistinguishedField to
get your value:
public override object GetDistinguishedField(string
dottedPath)
{
    XsdDistinguishedFieldDefinition dFDef = (XsdDistinguishedFieldDefinition)
base.GetDFDef(dottedPath);
    object val = base._getXPath(dFDef.XPath, dFDef.IsDynamic);
    if (val == null)
    {
        return null;
    }
    if (val.GetType() != dFDef.FieldType)
    {
        val = XmlHelpers.ChangeType(val, dFDef.FieldType);
    }
    return val;
}

This method will return null if the element/attribute doesn’t exist otherwise it will
attempt to convert (cast) the value to the appropriate type.

However, the InvalidCastException arises
from your orchestration.
Let’s assume you had a Distinguished Field called isSuccessful which is of type boolean.

When you write something like

if (Response.isSuccessful)

in an expression shape, the code generated is this:

if (!((bool) __ctx2__.__Response.part.GetDistinguishedField(“isSuccessful”)))

Ahah! The orchestration does an explicit cast of the Distinguished Field value to
a bool.
And an explicit cast of null to a bool will raise an InvalidCastException.

However, an explicit cast of null to a string is fine.

So if you had a Distinguished Field called employeeName of type string, then the same
code would be:
if (!((string) __ctx2__.__Response.part.GetDistinguishedField(“employeeName”)))

And no exception would be raised.

Conclusion

If you’re using Distinguished Fields with types other than string, and the element/attribute
you’re referring to is optional then you must check that the element/attribute exists
before attempting to set/get a value.

In most cases, you’d do this by using the xpath() function
in an orchestration
(e.g. getting a count of the element/attribute, and checking that count >
0)

Just FYI….!

Back to Tech Blog