2

Inside a BizTalk Expression shape, I'm presented a blank text editor with some crude "examples" above, mocking me. "It's so easy" they chant. Try as I might, I'm just not making the connection. Maybe I'm over thinking it. I'm a BizTalk newbie. Coming from many years of heavy .NET and software engineering experience, my think doesn't seem to brain...

Would someone with great BizTalk experience enlighten me on this question: What is in scope and available for use inside the Expression shape? And subsequently, the MessageAssignment shape as well?

By scope, I mean like in real programming: Variable names, namespaces, etc.

Every example I see on BizTalk assumes you understand where these things come from. For instance, see this MSDN page: Using Distinguished Fields and Property Fields

It assumes I know where "MyMessage" is created, instanced, and accessible. I have no clue where to initialize it, what shape identifier to give a name, etc.

My design seems simple: When an error occurs, catch it, create an ErrorMessage out of thin air, assign string value to a distinguished field "Reason", and send to a send port. I can get everything but the expression right.

Any expert insight is greatly appreciated.

Dijkgraaf
  • 11,049
  • 17
  • 42
  • 54
ryancdotnet
  • 2,015
  • 16
  • 33

2 Answers2

4

You can only create a message inside a Construct Message shape and then either Map or an Assignment shape in side that. You can NOT construct a message in an expression shape.

Map option

For a map in an Exception block, the only messages you can map from are those that were created before the scope that the Exception block is in. So for an exception block for the whole Orchestration I map from the message received in the initial activating receive (which should be before the scope) and too the error message schema. Then you can have a message assignment in the Construct shape after the map.

Note: This initial received message is the only one you will be certain of having in an Orchestration if the scope covers all but the Initial Receive. I have only had it once in an edge case involving a badly formatted MIME message that caused the Orchestration to start up but not have this initial message.

Non map options

Creating it without a map using only a Assignment shape you either

  1. need to call an external class e.g. The ESB Fault handling eSBFault = Microsoft.Practices.ESB.ExceptionHandling.ExceptionMgmt.CreateFaultMessage(); where eSBFault is defined as Message Type Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults.FaultMessage
  2. Assign it from another existing message e.g. xTempDoc= wcfFault.fault; where in this example wcFault is the Exception Object Name set in the Catch Exception and xTempDoc is a Variable of type of System.Xml.XmlDocument that is then assigned to a message variable.

  3. Manually create the message e.g below from creating a new message in the Message Assign shape

Example

xmlDocMessage = new System.Xml.XmlDocument();
xmlDocMessage.LoadXml("<Out><ErrorCode>4711</ErrorCode></Out>");

Creating a Message variable

For all of the above you need to go into the Orchestration view and create a Message variable of that name of the message and set it to the Message Type of the message you want to construct. It needs to be in the scope where you are constructing it or a an enclosing scope. Note: It will only be available in the scope where you define it or an child scope of the scope where it is defined.

enter image description here

Other limitations of the Expression Shape

For other limitations of the Expression shape see Requirements and Limitations for Expressions

Dijkgraaf
  • 11,049
  • 17
  • 42
  • 54
  • Thank you for your answer. This does help me in my sub-question of "creating a message out of thin air", but I still need to know where, in your example, "xmlDocMessage" is instanced. If I paste your code into my MessageAssignment shape, it gives this error message: "identifier 'xmlDocMessage' does not exist in 'catch'; are you missing an assembly reference?" – ryancdotnet Jun 21 '16 at 21:17
  • 1
    You need to go into the Orchestration view and create a Message variable of that name and set it to the Message Type of the message you want to construct. It needs to be in the scope where you are constructing it or a an enclosing scope. – Dijkgraaf Jun 21 '16 at 22:25
  • Great edit! This definitely helped me piece things together. With your example, I now see that anything that is defined at the Orchestration level OR the ___Scope level (if I'm inside that scope) is available to an Expression/MessageAssignment shape via XLANG. That helps quite a bit! Thanks! – ryancdotnet Jun 22 '16 at 18:50
3

@Dijkgraaf's answer is excellent, but technically speaking the expression editor is giving you access to the XLANG/s language. AFAIK you still have to declare variables as he illustrated (using the orchestration toolbox window). However, the language itself is somewhat similar to C# and .NET, and you can technically do just about anything in an expression shape that you could otherwise do in other shapes, using the proper keywords.

For example, it's possible to construct a message in an expression shape like so (taken from this blog):

construct OutboundMessage {

    XmlDocument.LoadXml(
      @"<?xml version='1.0' standalone='yes' ?>
        <Root id='012345' xmlns='http://schemas.sample.org/BizTalk/2010/input' />
    ");

OutboundMessage = XmlDocument;
}

Typically, this is a bad idea. You should ordinarily use the regular construct message shapes - why? Because when you go to look at your orchestration a year later (or someone else does), it will be immediately obvious where you're constructing messages. Same can go for decision shapes - a decision shape might be overkill in some cases, but it will be immediately obvious to a future developer that there's decision logic (instead of looking for an if statement in an expression). Expression shapes should:

  1. Always be properly named/labeled. Don't leave yourself trying to figure out what Expression_2 is actually doing, name it something useful like "Increment Loop Counter"
  2. Avoid lengthy expressions. The editor is not very friendly (very limited intellisense, no highlighting, no automatic formatting). More than once I've lost code in an expression shape by hitting Esc instead of clicking OK and not realizing what I had done immediately. It's very good for XLANG/s specific things (like using the xpath function, or accessing distinguished fields, or doing simple things). If you're getting into more complicated logic, have your code call out to a C# helper library that the orchestration project references.
Dan Field
  • 20,885
  • 5
  • 55
  • 71
  • Do shape names ever get referenced in XLANG or code? As in, do they need to follow strict variable naming schemas? Or are they for display only, and can be descriptive like your example without ill effect? "Increment Loop Counter" – ryancdotnet Jun 22 '16 at 18:53
  • 1
    Shape names are descriptive only. – Dan Field Jun 22 '16 at 18:53