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 existBizTalk 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....!

Original from:http://www.bizbert.com/bizbert/2007/11/15/Distinguished+Fields+And+Optional+Elements.aspx

原文地址:https://www.cnblogs.com/zhaobin/p/2050325.html