Message Header vs. Context Terminology


Is anyone confused about the conflicting terminlogy I have seen in the BizTalk documentation regarding BizTalk message headers and contexts? I have always understood a message to be just a context and a body.  There is no 'header' in a BizTalk message that has been received by an adapter.   For instance, here is an exerpt from the product documenation and I have seen this terminlogy conflict in other whitepapers and documentation.


A message is made up of a header section and a body section:


·                      Headers are simple name-value pairs. The names are all drawn from various property schemas. The system provides some core schemas and BizTalk Server applications can add their own.



I believe this should read:


A message is made up of a context and a body:


·                      The context is composed of simple name-value pairs. The names are all drawn from various property schemas. The system provides some core schemas and BizTalk Server applications can add their own.

Comments (7)
  1. It might be worth talking about how a Message can be made up of multiple parts (of which one is designated as the body) – however there is a single ‘Context’ that applies to all parts.

    (Also – it is possible that each message part can have it’s own Name/Value Pair collection. ‘msgpart.SetProperty(n,v)’

    BUT…during msg processing I havent found a way to ‘enumerate’ all these properties (like you can do with Context props)….and if you find any documentation….I’m all ears….

    Great site!! Will let my world know about it!!

    Keep it up!

    Cheers,

    Mick.

  2. mmckeown says:

    thx Mick. I will add a post to your site as well. Give me a description of your blog – looks like a lot of BTS technologies you support.

    So you are looking to find a way to enumerate the name/value pairs (properties) for each individual message part?

  3. ToddVan says:

    You might also want to point out that there are size limitations to the data that can be embedded in these properties 😉

  4. mmckeown says:

    thx Todd. So are you saying there is not sufficient documentation regarding size limitations of properties in a message context?

  5. Mike says:

    Here is the code to enumerat through the context properties that Mick Badran asked for above.

    #region References

    using System;

    using System.Xml;

    using System.Xml.Schema;

    using System.IO;

    using System.Text;

    using System.Reflection;

    using System.Collections;

    using System.Diagnostics;

    using Microsoft.XLANGs.BaseTypes;

    using Microsoft.XLANGs.Core;

    using BTS;

    using BTF2;

    using ENI.SI231.Common;

    #endregion

    namespace ENI.SI231.IntegrationEngine

    {

    [Serializable]

    public class MessageUtility

    {

    #region Constants

    private const string CONTEXT_PROPERTIES = "Context Properties";

    private const string CONTENT_PROPERTIES = "Content Properties";

    private const string PART_PROPERTIES = "Part Properties";

    private const string PART_SCHEMA = "Part Schema";

    private const string PART_STREAM = "Part Stream";

    private const string LINE = "—————————————————————";

    private const string NONE = "None";

    private const string PROPERTY_FORMAT = "{0}: {1}";

    private const string PART_FORMAT = "Part Name: {0}";

    private const string SOURCE = "BizTalk Utilities";

    private const string ERROR_MESSAGE_FORMAT = "Class: {0} Method: {1} : Message: {2}";

    #endregion

    #region Fields

    private XLANGMessage message;

    // private XmlDocument xmlDoc;

    #endregion

    #region Constructors

    public MessageUtility()

    {

    }

    public MessageUtility(XLANGMessage message)

    {

    this.message = message;

    }

    #endregion

    #region Properties

    public XLANGMessage Message

    {

    get

    {

    return message;

    }

    set

    {

    message = value;

    }

    }

    public XmlDocument XmlMessage

    {

    get

    {

    return (XmlDocument)message[0].RetrieveAs(typeof(XmlDocument));

    }

    }

    #endregion

    #region Public Methods

    /// <summary>

    ///

    /// </summary>

    public void TraceProperties()

    {

    try

    {

    if (message != null)

    {

    bool ok;

    object value;

    Type[] types;

    Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();

    if (assemblies != null && assemblies.Length > 0)

    {

    // Context Properties

    Trace.WriteLine(LINE);

    Trace.WriteLine(CONTEXT_PROPERTIES);

    Trace.WriteLine(LINE);

    ok = false;

    for (int j = 0; j < assemblies.Length; j++)

    {

    if (assemblies[j] != null)

    {

    types = assemblies[j].GetTypes();

    if (types != null)

    {

    for (int i = 0; i < types.Length; i++)

    {

    if (types[i].BaseType == typeof(MessageContextPropertyBase))

    {

    value = message.GetPropertyValue(types[i]);

    if (value != null)

    {

    Trace.WriteLine(string.Format(PROPERTY_FORMAT, types[i].FullName, value));

    ok = true;

    }

    }

    }

    }

    }

    }

    if (!ok)

    Trace.WriteLine(NONE);

    // Content Properties

    Trace.WriteLine(LINE);

    Trace.WriteLine(CONTENT_PROPERTIES);

    Trace.WriteLine(LINE);

    ok = false;

    for (int j = 0; j < assemblies.Length; j++)

    {

    if (assemblies[j] != null)

    {

    types = assemblies[j].GetTypes();

    if (types != null)

    {

    for (int i = 0; i < types.Length; i++)

    {

    if (types[i].BaseType == typeof(MessageDataPropertyBase))

    {

    value = message.GetPropertyValue(types[i]);

    if (value != null)

    {

    Trace.WriteLine(string.Format(PROPERTY_FORMAT, types[i].FullName, value));

    ok = true;

    }

    }

    }

    }

    }

    }

    if (!ok)

    Trace.WriteLine(NONE);

    }

    }

    }

    catch (Exception ex)

    {

    EventLog.WriteEntry(SOURCE,

    string.Format(ERROR_MESSAGE_FORMAT,

    MethodInfo.GetCurrentMethod().ReflectedType.ToString(),

    MethodInfo.GetCurrentMethod().ToString(),

    ex.Message),

    EventLogEntryType.Error);

    }

    }

    public void TraceParts()

    {

    try

    {

    if (message != null &&

    message.Count > 0)

    {

    IEnumerator e = message.GetEnumerator();

    XLANGPart part;

    XmlSchema xmlSchema;

    XmlDocument xmlDocument;

    Type type = typeof(Microsoft.XLANGs.BaseTypes.Size);

    Assembly assembly = type.Assembly;

    Type[] types = assembly.GetTypes();

    StringWriter writer;

    object value;

    bool ok;

    while (e.MoveNext())

    {

    part = (XLANGPart)e.Current;

    if (part != null)

    {

    Trace.WriteLine(string.Format(PART_FORMAT, part.Name));

    Trace.WriteLine(LINE);

    if (types != null)

    {

    Trace.WriteLine(PART_PROPERTIES);

    Trace.WriteLine(LINE);

    ok = false;

    for (int i = 0; i < types.Length; i++)

    {

    if (types[i].BaseType == typeof(PartContextPropertyBase))

    {

    value = message.GetPropertyValue(types[i]);

    if (value != null)

    {

    ok = true;

    Trace.WriteLine(string.Format(PROPERTY_FORMAT, types[i].Name, value));

    }

    }

    }

    if (!ok)

    Trace.WriteLine(NONE);

    }

    Trace.WriteLine(LINE);

    Trace.WriteLine(PART_SCHEMA);

    Trace.WriteLine(LINE);

    xmlSchema = part.XmlSchema;

    writer = new StringWriter();

    xmlSchema.Write(writer);

    Trace.Write(writer.ToString());

    Trace.WriteLine(LINE);

    Trace.WriteLine(PART_STREAM);

    Trace.WriteLine(LINE);

    xmlDocument = (XmlDocument)part.RetrieveAs(typeof(XmlDocument));

    Trace.Write(xmlDocument.OuterXml);

    Trace.WriteLine(LINE);

    }

    }

    }

    }

    catch (Exception ex)

    {

    EventLog.WriteEntry(SOURCE,

    string.Format(ERROR_MESSAGE_FORMAT,

    MethodInfo.GetCurrentMethod().ReflectedType.ToString(),

    MethodInfo.GetCurrentMethod().ToString(),

    ex.Message),

    EventLogEntryType.Error);

    }

    }

    public void TraceAll()

    {

    TraceProperties();

    TraceParts();

    }

    public string GetPartSimpleValue(XLANGPart part)

    {

    XmlDocument document;

    document = (XmlDocument)part.RetrieveAs(typeof(XmlDocument));

    return document.DocumentElement.InnerText;

    }

    #endregion

    }

    }

  6. jenzo says:

    Request for more documentation:

    1) In developing an Adapter I want to define some global context properties, i.e. "MyAdapter.NativeAddress". I have deployed the property schema (can see it in HAT, port filters, etc), but I can’t use it in my Orchestration expression — there’s no documentation on this one. Why can’t I assign a value to my custom property just like I can with, say, "BTS.MessageID"? Thanks in advance.

    2) I want to add my adapter to the list that can be bound within an orchestration ("specify now"). Is this an undocumented registration option — how do I do this?

  7. Mike says:

    Hi Jen

    Hope this answers your questions…

    1) – You need to derive your properties in their property schema from MessageContextPropertyBase – this is the Propery Schema Base property on each property schema item.  This lets the orchestration designer know that the property is just a context property – not necessarily expected to be found in the message itself via promotion.

    2) I don’t believe this list is extensible – plus they shouldn’t really want people to use this "early binding" anyway – it is really only useful for quick and dirty demos.

Comments are closed.

Skip to main content