Be.Stateless.BizTalk.Abstractions
Build Pipelines
Latest Release
Release Preview
Overview
Be.Stateless.BizTalk.Abstractions
is part of the BizTalk.Factory Runtime Package. This component provides various abstractions over Microsoft BizTalk Server®’s message contexts and context properties.
Message Context Abstractions
There is some amount of idiosyncrasies coming with Microsoft BizTalk Server® and the API to manipulate —i.e. reading, promoting, or writing— message context properties certainly comes with its shares of oddities.
Message Context API
First and foremost, accessing the context property must be done in two very distinct ways depending on whether the property needs to be accessed from an IBaseMessage
or an XLANGMessage
-based message instance. The IBaseMessage
API is even more awkward as one must most often instantiate some sort of context property descriptor in order to get a QName that will ultimately allow one to get both the context property’s local and namespace names to pass to the API method.
Then, the value returned be the reading API is always of type object
and it must always be explicitly casted to the exact concrete type of the property, which requires extra caution to handle null
values when reading value type properties.
Finally, deleting a property value from the message context is generally awkward as none of the IBaseMessage
and XLANGMessage
API exposes a Delete()
method. Does one have to assign a null value or an empty string to the property? Does this work the same way with both IBaseMessage
and XLANGMessage
APIs?
Take a look at the following couple of code samples that demonstrate how to read context properties with the native APIs.
Sample 1 - Accessing context properties using the built-in IBaseMessage
API.
public void ProcessMessage(IBaseMessage message)
{
...
var messageTypeProperty = new BTS.MessageType();
string messageType = (string) message.Context.Read(
messageTypeProperty.Name.Name,
messageTypeProperty.Name.Namespace);
var enqueuedTimeProperty = new SBMessaging.EnqueuedTimeUtc();
object value = message.Context.Read(
enqueuedTimeProperty.Name.Name,
enqueuedTimeProperty.Name.Namespace);
DateTime enqueuedTime = value != null ? (DateTime) value : default;
...
}
Sample 2 - Accessing context properties using the built-in XLANGMessage
API.
public void ProcessMessage(XLANGMessage message)
{
...
string messageType = (string) message.GetPropertyValue(
typeof(BTS.MessageType));
object value = (DateTime) message.GetPropertyValue(
typeof(SBMessaging.EnqueuedTimeUtc));
DateTime enqueuedTime = value != null ? (DateTime) value : default;
...
}
Now, contrast them with the following 2 code excerpts that demonstrate the use of a unique, regular, and type-safe API to manipulate message context properties. This new strongly-typed API is made available through extension methods provided by BaseMessage as wrappers around the built-in IBaseMessage
and XLANGMessage
APIs.
Sample 3 - Accessing context properties using BizTalk.Factory
’s IBaseMessage
extension methods.
public void ProcessMessage(IBaseMessage message)
{
...
string messageType = message.GetProperty(BtsProperties.MessageType);
DateTime? enqueuedTime = message.GetProperty(SBMessagingProperties.EnqueuedTimeUtc);
...
}
Sample 4 - Accessing context properties using BizTalk.Factory
’s XLANGMessage
extension methods.
public void ProcessMessage(XLANGMessage message)
{
...
string messageType = message.GetProperty(BtsProperties.MessageType);
DateTime? enqueuedTime = message.GetProperty(SBMessagingProperties.EnqueuedTimeUtc);
...
}
Notice that besides being shorter, they are more importantly identical, regardless of whether the message is an IBaseMessage
or an XLANGMessage
instance. They do not require any explicit casting. They leverage Nullable<T> for properties that are value types and would otherwise not support null
values without explicit special case handling.
For the record, BizTalk.Factory
moreover provides IBaseMessageContext
extension methods that support the exact same API to either delete, promote, read or write context properties given an IBaseMessageContext
object, see BaseMessageContext.
MessageContextProperty<T, TR> Abstraction
The previous extension-method-based API comes with 2 requirements:
-
Each context property that needs to be accessed must derive from MessageContextPropertyBase. This usually means that the property must be defined as a
MessageContextPropertyBase
in aProperty
schema, but as one will see, the property could be defined in plainC#
if one does not require the property to take part into subscription filters (e.g. send port’s filters); -
A MessageContextProperty<T, TR> accelerator needs to be instantiated for each context property that needs to be accessed via this API.
While the original IBaseMessage
API only requires a pair of namespace and local name strings, this API requires types to be defined. But this is not really an issue as the XLANGMessage
API requires types to be defined anyway. The benefits of defining such types therefore far outweigh their costs:
-
There can be no longer be usage discrepancies between both
IBaseMessage
andXLANGMessage
APIs as the API is now the same whether the message object being used derives from one type or the other; -
Local and namespace names’ magic strings never have to be used anymore;
-
Properties are always handled in a type-safe way, even the value type ones.
Because instantiating these context property’s type-accelerators on demand is tedious and cumbersome, BizTalk.Factory
readily provides most of them as static properties defined in a bunch of classes:
-
BizTalkFactoryProperties provides the accelerators for the context properties that belong to
BizTalk.Factory
and cannot be used in publication/subscription filters.
Note thatBizTalk.Factory
also provides accelerators for its context properties that are meant to be used in publication/subscription filters, see BizTalk.Schemas’ Property Schemas; -
BtsProperties provides the accelerators for the Microsoft BizTalk Server®’s core system context properties, see BTS namespace;
-
EdiProperties and OverridableEdiProperties provides the accelerators for the Microsoft BizTalk Server®’s
EDI
context properties, see EDI and EdiOverride namespaces; -
ErrorReportProperties provides the accelerators for the Microsoft BizTalk Server®’s context properties related to error reporting, see ErrorReport namespace;
-
FileProperties provides the accelerators for the Microsoft BizTalk Server®’s context properties related to the
File
adapter, see FILE namespace; -
HttpProperties provides the accelerators for the Microsoft BizTalk Server®’s context properties related to the
HTTP
adapter, see HTTP namespace; -
Pop3Properties provides the accelerators for the Microsoft BizTalk Server®’s context properties related to the
POP3
adapter, see POP3 namespace; -
SBMessagingProperties provides the accelerators for the Microsoft BizTalk Server®’s context properties related to the
SB-Messaging
adapter, see SBMessaging namespace.
Remark Take notice of another Microsoft BizTalk Server® oddity: the
SB-Messaging
adapter does not make use of theCustomBrokeredMessagePropertyNamespace
context property in its ownXML
namespace, but uses instead theCustomBrokeredPropertyNamespace
context property in the WCFXML
namespace, see WcfProperties;
-
SapProperties provides the accelerators for the Microsoft BizTalk Server®’s context properties related to the
SAP
adapter, see Message Context Properties for Receiving IDOCs; -
SftpProperties provides the accelerators for the Microsoft BizTalk Server®’s context properties related to the
SFTP
adapter, see SFTP namespace; -
WcfProperties provides the accelerators for the Microsoft BizTalk Server®’s context properties related to the
WCF
adapters, see WCF namespace.
Context Properties
For each context property that needs to be accessed via the previously mentioned API, a type deriving from MessageContextPropertyBase
must be defined so that its MessageContextProperty<T, TR>
accelerator counterpart can be defined in turn.
However, not all of the standard or out-of-box context properties are backed by property schemas. They therefore do not have a corresponding MessageContextPropertyBase
-derived type definition. To make these properties nonetheless usable through the BizTalk.Factory
API, Be.Stateless.BizTalk.Abstractions
fills the gap and provides plain C#
type definitions —or pseudo property schemas— for the most meaningful ones.
Remark These context properties only need a plain
C#
type definition and should not be backed by property schemas as they are not intended to be used in publication/subscription filters.
-
BizTalkFactory.Properties declares types for
BizTalk.Factory
’s own context properties that cannot be used in subscription filters; -
Edi.Properties declares types for
EDI
context properties that do not have a correspondingMessageContextPropertyBase
-derived type definition; -
Sftp.Properties declares types for
SFTP
context properties that do not have a correspondingMessageContextPropertyBase
-derived type definition; -
System.Properties declares types for
BTS
core system context properties that do not have a correspondingMessageContextPropertyBase
-derived type definition.
Remark Because these context properties now have corresponding type definitions, they can finally be used in XLANG/s expressions too, for instances:
variable = message(EDI.BGM1_1)
or
message(Be.Stateless.BizTalk.Schemas.BizTalkFactory.DisableTransportRetries) = true
.
They still, nonetheless, cannot be used in a subscription filter or correlation set.
Fluent API
Be.Stateless.BizTalk.Abstractions
also provides a fluent API, thanks to extension methods defined by the various classes in the Be.Stateless.BizTalk.ContextProperties.Extensions namespace, to speed up and chain the assignment of the context properties it defines or brings to the surface.
Developer Help
Detailed developer help has been provided as XML
comments directly embedded in source code. Though developers usually browse through this documentation while developing thanks to, for instance, JetBrains ReSharper quick help —ctrl+shift+F1, an online version of this inlined help has also been provided here for greater reachability: