BizTalk messages have both a body and a context. Values existing in the context of the message are the equivalent of the things you would write on the envelope of a piece of mail, where the body is what's written on the letter inside. Context property values are used for routing messages to subscriptions, but they can also be used to do neat stuff inside of pipelines, as they are easily accessible.
How do values get placed inside the context of a message? They are either put there by an adapter, a pipeline component, or an orchestration expression. However, the way this happens is tied directly to an often-overlooked setting in BizTalk property schemas: the Property Schema Base.
What is Property Schema Base? The property description in Visual Studio says "This property indicates the BizTalk base class that is used when generating the .NET type for this property. Default value is 'MessageDataPropertyBase'." Sounds like one of those obscure properties you can leave set to the default value, doesn't it? No. Don't even think about skipping over this property without thinking about the consequences, especially because the default is often not what you want.
There are three choices for this property, only two of which you'd really conceivably use, and only one of which makes the most sense the majority of the time. Using MessageDataPropertyBase, the default, means that there must be an element or attribute in the body of the message that has its value promoted to this property in order for the property to appear in the context of the message. MessageContextPropertyBase does not have this restriction - you can write any old value you like into this property's value in the context.
Let's say I've got a schema, MySchema, that has no promoted properties; i.e. I didn't use the Promote > Show Promotions > Property Fields tab in the schema designer. In an orchestration, I create a MySchema message called MyMsg, and I want to assign some context properties using parentheses notation, like so:
If Prop1 and Prop2 are MessageContextPropertyBase properties, things work out like you would expect. They show up in Intellisense while you are typing, and when the message gets sent out of the orchestration, the properties are promoted.
If Prop1 and Prop2 are MessageDataPropertyBase properties, they don't show up in Intellisense, and you get a red squiggly if you type them in yourself. What's wrong? The values aren't promoted in the schema of your message. If you open up MySchema and promote an element or an attribute to one of your MessageDataPropertyBase properties, rebuild, and try again, the property will show up in Intellisense with a different mini-icon than the other context properties. Actually, there's some funky behavior in Visual Studio where if your property schema is in another project (regardless of whether it's in a referenced DLL or a referenced project in this solution), MessageDataPropertyBase properties won't show up in the initial Intellisense pop-up - you need to type in the .NET namespace first and press "." and then any MessageDataPropertyBase properties will show up.
This difference may seem trivial, but it has important effects on the way that context properties can be used in your workflows. At a recent job, my client had a fairly sophisticated tracking system implemented within BizTalk to feed information about messages into BAM tables, and a web GUI could be used to access and view that tracking information. The system was based on a custom property schema and reusable pipeline components that wrote certain properties to the BAM tables. In order to get "end-to-end tracking," you needed to take the properties from the original message and promote them in your orchestration (if applicable) to the outbound message, so when it passed through the pipeline component on the send side, all the values would be registered with a successful send action.
Unfortunately, when the client had implemented the property schema (which was now a dependency of many, many projects and couldn't be changed without massive headaches), they never changed the default Property Schema Base. This isn't a problem if your outbound message has all of the tracking information as values somewhere in the message body. But what if the output of the orchestration is a message that doesn't have data fields for all that information? You're out of luck, and you have to use the official workaround: At the end of the orchestration, if everything was successful, send the inbound message (with all of its context properties still attached) back out through a pipeline with the send-side tracking component. Of course, you didn't want these messages hanging around, so you shouldn't send it to a folder to a queue. Where was the accepted place to send it? Through the HTTP adapter to an ASP page, installed on the local IIS instance, that does nothing. =)
You can use the Property Promotion dialog to promote field values to properties regardless of whether they are MessageDataPropertyBase or MessageContextPropertyBase properties. So why would you ever want to use MessageDataPropertyBase properties? You would want to use them if it is appropriate for your architecture. MessageContextPropertyBase properties are globally accessible - if someone can reference your property schema, they can use the MessageContextPropertyBase properties in it. In the case of the tracking system above, the properties used for tracking should have been globally accessible. However, let's say I'm creating a workflow with two different orchestrations - I want MoneyTransfer messages with a Value over 1,000,000.00 to go into one orchestration, and the rest of the MoneyTransfer messages to go into the other orchestration. In this case, it doesn't really make sense for the Value data to be in the context of any messages besides MoneyTransfers, and it's always going to be in the body of the inbound message, so it makes the most sense for it to be a MesssageDataPropertyBase property. Note that this doesn't expressly stop others from using it: they could reference your assembly as a property schema and promote values from their schema to your properties. However, it prevents your property from showing up in the global list, where it doesn't really belong.