Suppose you have taken over someone else’s BizTalk orchestration, and it’s huge. You make some changes, and you get a compile error like this:


 error X2110: use of unconstructed message 'ExceptionMsg'

Sometimes you can click on the error, and it will take you to the proper location. If that doesn’t work, here the “secret trick”.

Rename the message in the Orhcestration View. For example, put a “2” or the word “bad” on the end.

Now, go to the Orchestration, and scroll down looking for the red exclamation points. That should show you everywhere that message is used.

Now, you should be able to find the cause of the error with a little scrolling and opening a minimal number of shapes.

Same tricks works for variables, to find or cross reference where a variable is used in the orchestration.

Sometimes, links on the Microsoft and MSDN sites disappear or move, so I made a copy of the architecture diagram from BizTalk. It hasn’t been updated since then; while new features have been added, the architecture really hasn’t changed.

BizTalk Server 2009 Runtime Architecture Poster


NOTE: Download the above file (right-click Save-AS), then open with Adobe Acrobat PDF reader, and zoom in to the desired section. This is a wall-size poster.

Below are some other common architecture diagrams that appear in the above poster in a slightly different form:

BizTalk Architecture Diagrams/Images/Pictures

Overall Message Flow

RecivePort/ReceivePipeline

SendPort/SendPipeline

Had to fix some code today left by a prior BizTalk developer.

Error:

Shape name: CreateTableTypeLogMessage
ShapeId: 734241d3-f9aa-41da-8696-511010d815f7
Exception thrown from: segment 2, progress 102
Inner exception: There is no value associated with the property ‘EDI.ISA_Segment’ in the message.

Explanation:

When you drop an EDI file, all these fields will exist, and the code would work properly. I was testing by dropping an XML file (the same as created by the BizTalk EDI Receive Pipeline). When you drop an XML file, there are of course no promoted EDI fields. So the developer should check for this and handle accordingly (substituting some dummy/null values instead).

In this case, in Production the error wouldnot occur, becausse there we would presumably always be dropping EDI files. But it is nice to have the flexibility to drop an XML X12 file when needed.

See the “Code Before” shown below. This was in a catch exception block under a scope. The developer was logging almost all the fields in the ISA/GS headers. BizTalk provides promoted fields for some of them, but not all. So he had helper routine in C# which would return the nth item of header.

Code Before:

<pre>
isaSegment = msgInbound(EDI.ISA_Segment);
gsSegment = msgInboundEDI.GS_Segment);

xpath(msgError,"/*[local-name()='usp_InsertEDILogRecords']/*[local-name()='EDILogRecords']/*[local-name()='udtt_EDITransactionLog']/*[local-name()='ISASender']") = Inbound_CPChemX12(EDI.ISA06);

xpath(msgError,"/*[local-name()='usp_InsertEDILogRecords']/*[local-name()='EDILogRecords']/*[local-name()='udtt_EDITransactionLog']/*[local-name()='ISADate']") = CPChemHelpers.StringSplitter.SplitString(isaSegment,'*',9);

</pre>

After: Using the “exists” keword

You can make sure the promoted field is there by using the “exists” syntax.
“if (promotedField exists message)” is the syntax, where “exists” is the literal keyword, and the other two would be your values.

NOTE: You cannot use an “if” statement in a “message assignment shape”, only in an “expression shape”. So you would have to set some of these values in an expression shape in variables, and then use those variables in the message assignment shape. So the code below would NOT work as is.

The other alterantive is to use the BizTalk Decide Shape, and have two construct/message-assignment shapes, such that only the appropriate one would execute.

<pre>
if (EDI.ISA_Segment exists msgInbound)
  {
     isaSegment = msgInbound(EDI.ISA_Segment);
     gsSegment = msgInboundEDI.GS_Segment);

     xpath(msgError,"/*[local-name()='usp_InsertEDILogRecords']/*[local-name()='EDILogRecords']/*[local-name()='udtt_EDITransactionLog']/*[local-name()='ISASender']") = Inbound_CPChemX12(EDI.ISA06);

     xpath(msgError,"/*[local-name()='usp_InsertEDILogRecords']/*[local-name()='EDILogRecords']/*[local-name()='udtt_EDITransactionLog']/*[local-name()='ISADate']") = CPChemHelpers.StringSplitter.SplitString(isaSegment,'*',9);
  }
else 
  {
     // put blank or other values in those fields as desired. 
  }
</pre>

Decide Shape Solution

The rule itself can be set in the Properties window or by click on the Decide shape. There is a red exclamation here because I changed the message name when I took the screen shot.

Scenario/Issue

You drop an EDI file into a disk directory associated with a BizTalk Receive Location.

Using Tracking or Routing, you see that the XML created begins with this:

<pre>
<ns0:X12_00401_204 xmlns:ns0="http://mycompany.com/X12/204/App2">
  <ST>
    <ST01>204</ST01>
    <ST02>0001</ST02>
  </ST>
</pre>

but you are expecting the namespace to look like this:

<pre>
<ns0:X12_00401_204 xmlns:ns0="http://mycompany.com/X12/204/App">
</pre>

Question

Why is the namespace wrong? How and where does BizTalk know what namespace to use here?

One Possible Reason

Where I was recently working, I was working on a Version 2 of the system, while another developer was still making modification to Version 1. So that we wouldn’t conflict, I change the end of the namespace from /MyApp to /MyApp2.

When testing with XML, that works fine. But when testing by dropping EDI/X12 files, there is a conflict between the two developers.

Check the Party/Agreeement

When you have a BizTalk EDI Receive Pipeline on the receive location, the default process is that BizTalk uses the company name id and qualifier to find the Party in the Trading Partner Management (TPM) system, aka the “Parties”.

If Biztalk Admin console, expand the Parties and find the Party you are testing. If you are not sure which party goes with your qualifier and ID in your EDI file, you can run this SQL to XREF EDI Qualifier to BizTalk party name.

Each party can have one or more agreements. Try to find the X12 agreement and open it. At the top, there will be two tabs: YourCompany->Party and Party->YourCompany. Since we are receive an EDI file, click the “Party->YourCompany” tab.

Then find the document you are dealing with by number, e.g. 204, 850, 855 etc… in the “Transaction Type” column. Then scroll right to the “Target namespace” column. The value there is what should appear in the XML.

Also check the “Local Host Settings

In a BizTalk map, you can add scripting functoids without connecting them to anything. They can contain functions, as shown below.

Note 1: You must add a constant for each variable, so if you have 3 parameters, then add three constants values on the “Functoid Inputs” tab.

Note 2: They will have a warning icon on them, indicating no inputs or outputs.

Now, anywhere else in the map, you can add a Scripting Functoid, and simply call the shared C# function from above:

A better approach is probably have to have a C# Map.Helpers class/assembly where you have all the reusable functions. Then you can also re-use them across different maps.

Over time, I have found or developed several T-SQL (Transact-SQL) commands that you can run to help cross reference (XREF) various BizTalk entities. Most of these run against the BizTalkMgtmDB database.

Here is a list of them, so they are easy to find:

BizTalk SQL Queries

1. Simple list of Receive Ports and Receive Locations
2. Xref BizTalk Maps to Ports (Sends and Receive Ports)
and looks like I blogged this twice: SQL to find all BizTalk Maps on all Send and Receive Ports
3. BizTalk SQL to XRef Send/Receive Ports to Orchestrations
4. Find which Send Ports subscribe to which Receive Ports with SQL XREF query – based on RecivePortName= filters
5. XREF a BizTalk BTS.Operation back to the Orchestration Operation Name
6. Cross Reference BizTalk Receives bound to Orchestrations
7. Query and Join to show all BizTalk maps and map names (joining bt_MapSpec and bts_item)
8. SQL XRef BizTalk Pipelines to Sends/Receive Ports
9. XRef BizTalk Pipeline to Receive Locations

EDI SQL Queries

10. Xref SendPorts to BizTalk EDI Parties/Agreements
11. SQL to Lookup Parties based on Qualifier/Identifier (or list Party Names)
12. SQL to Retrieve BizTalk BatchingFilters for EDI Parties

Issue

As shown below – you type in “biztalk” and search, and no matches are found, even though installed BizTalk 2020 after Visual Studio 2019.

 

Solution

Open Visual Studio 2019 with “no code” option, i.e. you don’t have to create a project to get VS2019 to open. From the menus at the top, click “Extensions” then “Manage Extensions”.

In the manage extensions search box in the upper right, type in “BizTalk” and press enter to start the search.
Click on “BizTalk Server” and “Download” beside it (download is not shown in this image):

The VSIX Installer opens in a separate windows once you close Visual Studio. You must click the “Modify” button for it to start the install.


Let is run a while, it may take 2 to 5 minutes:

Finally, when it has completed after a few minutes, close the VSIX installer, then open Visual Studio again.

When you re-open Visual Studio now, click “Create a new project”, search for “biztalk” and now you should see the templates there. Usually, you will select ‘Empty BizTalk Server Project”.

This is what it looks like when it is correct:

Trying to delete a Send Port, you get this error:

SendPort ‘sp_ABC’ is being referenced by one or more TPM Parties. Please remove the Send Port reference(s) from the parties and retry deleting the Send Port (Microsoft.BizTalk.ExplorerOM)

By the way, TPM stands for “Trading Partner Management”.

Explanation

When you use EDISend Pipeline, BizTalk needs to know which Party to use, in order to put the correct identifiers and other fields in the ISA and GS segments of the EDI file.

One of the most common techniques for identifying the Party is to put the SendPort name in the X12_Agreement (found under “Parties” and then usually the name of the vendor or trading partner).

This creates a foreign-key relation or dependency in the database, and the SendPort cannot be deleted while it is being used in the X12 Agreement.

Parties can be found here in the BizTalk Admin Console. On the right, you will see a list of your trading partners (they might be customers or vendors for example):

Under the selected Party, choose the X12 agreement, and at the top, select the tab that says from your company to the trading partner. Click on “Send Ports” on the left. If you still want to delete your SendPort, find it in the list of SendPorts (one below is blurred to hide the name), then click the remove icon or word. That only disassociates the SendPort from the Agreement (it doesn’t actually delete the SendPort from the system).

But wait, there’s more! When you put a SendPort on an agreement, it get’s associated to the party as well. So there is a second place you have to remove it.

Now you should be able to go back to the Application and delete the SendPort.

If you are not sure which Party to select above, then I have a T-SQL query that cross-references Send Ports and parties.

How can you get values from the ISA/GS into variables in your BizTalk Orchestration?

Link to a good easy to read summary of ISA/GS segments in EDI:
https://www.availity.com/documents/ISA-IEA-GS-GE_QuickReference.pdf

I have included screen shots of their PDF here:

To get the Intellisense and compile/build to work, you will have to add a reference to Microsoft.BizTalk.Edi.BaseArtifacts.dll.

// define the variables that start with "str" and "char".
// msg204In in the message name that was in a prior receive shape. 
strISASegment = msg204In(EDI.ISA_Segment);
strGSSegment = msg204In(EDI.GS_Segment);

// position 103 always contains the field separator, 
// ISA Segment is fixed Length 
charEDIFieldSeparator = System.Convert.ToChar(strISASegment.Substring(103,1)); 

strISA13 = CSharp.Helpers.EDI.getEDIFieldFromSegment
      (strISASegment, charEDIFieldSeparator, 13); 
strGS06  = CSharp.Helpers.EDI.getEDIFieldFromSegment
      (strGSSegment,  charEDIFieldSeparator, 06); 

EDI.ISA_Segment and EDI.GS_Segment return the entire segment as a string. You will probably need a C# helper class to split based on the delimiter, as shown in the next code sample below.

The ISA Segment is fixed length and ends with three delimiter characters, for example: *:~.
That means the asterisk is the delimiter for fields, tilda is the delimiter for lines, and the colon is the delimiter for components or sub-elements (less frequently used). So you can get the field separator by doing a substring on character in the 104th position (103 if zero based).

public static class EDI
    {
        public static string getEDIFieldFromSegment(string stringToSplit, char separator, int positionToReturn)
        {
            string[] resultString;
            resultString = stringToSplit.Split(separator);
            if (resultString.Length >= positionToReturn)
                return resultString[positionToReturn];
            else
                return "getEDIFieldFromSegment:Error: Position Requested ${positionToReturn} greater than number of items ${resultString.length}";
        }

    }

NOTE: The above technique works with any and all ISA/GS fields. https://docs.microsoft.com/en-us/biztalk/core/edi-context-properties shows all the EDI fields available.

In other words, for these fields, you can do the following:

<pre>
strGS06 = msg204In(EDI.GS06);
</pre>

I found this related blog after I wrote the above: https://social.technet.microsoft.com/wiki/… But I’ve found that old blogs on Microsoft sites can often disappear and links don’t work after a few years. That blog also shows how to use the ISA/GS fields in a map by loading them into an XMLDocument.

Related Related MSDN forum discussion

The “ContextAccessor” is a third party tool that is also available to access these fields from maps, but it works differently. It uses a functoid to access the context fields, and has the ability to get each individual field. It was hosted on CodePlex, but I need to research where it’s new home resides.

Back to the basics of BizTalk. Even with years of experiences, sometimes you do something “stupid” and can’t figure out the error:

<pre>
The published message could not be routed because no subscribers were found. This error occurs if the subscribing orchestration or send port has not been enlisted, or if some of the message properties necessary for subscription evaluation have not been promoted. Please use the Biztalk Administration console to troubleshoot this failure. </pre>

For example, today I dropped my message into a file pickup folder, then Receive Location consumed it. I was expecting my orchestration to start, but instead I got the error above.

Here is a basic checklist:
1) Make sure you are using the right pipeline in your Receive Location, such as XmlReceive Pipeline or EDIReceive, so that it promotes the MessageType (as opposed to PassThruReceive).

2) Make sure you dropped the file in the correct folder, associated with the correct Receive Location

3) Make sure you dropped the correct file (it’s easy to copy/paste the wrong one). To make sure:

3a) The suspend will create a resumeable and not-resumable error. open the not-resumeable one, go the the “Messages” tab, double click the message, then go to the “Context” tab/link on the left, and find the the “Message Type” in the “Name” column, for example:

Remember that the message type is SchemaNamespace#SchemaRootElementName (the two values separated by a pound sign). Verify that there is a MessageType and that it is correct? Did you drop the wrong file?

3) Make sure that your orchestration bindings are correct. This was my issue today. I bound the orchestration to the wrong Receive Port.

Double-click the orchestration, then click “Bindings” on the left. Check the “Receive Ports” are properly matching the “Inbound Logical Ports”.

4) Use the “BizTalk Admin Subscription Viewer“.
See the link for sample of how this works. Basically, make sure that your orchestration is set to Activate on the correct MessageType (see explanation of MessageType above).

>