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
- Anonymous
January 02, 2006
The comment has been removed - Anonymous
January 03, 2006
The comment has been removed - Anonymous
January 03, 2006
You might also want to point out that there are size limitations to the data that can be embedded in these properties ;-) - Anonymous
January 03, 2006
thx Todd. So are you saying there is not sufficient documentation regarding size limitations of properties in a message context? - Anonymous
January 10, 2006
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
}
} - Anonymous
March 17, 2006
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? - Anonymous
March 21, 2006
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.