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
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:

strGS06 = msg204In(EDI.GS06);

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:

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. 

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).

Open the “BizTalk Server Administration Tool/Console”, expand the hierarchy on the left, and click on the “BizTalk Group”. From there, click on the tab at the top labeled “New Query”. The “Field Name” should already be populated with “Search for” and you need to use the drop-down box to pick “Subscriptions” for the “Value” column, then click “Run Query”.

Then find your orchestration preceded by the word “Activate”.

Click on it then go to the expression tab. This is where you will find the subscription for your orchestration. If you are using the “specify later” binding, it will be a ReceivePort name, and will typically have a message type, which is namespace#rootelement (from your schema).

To correlate the ReceivePort name to the GUID above, you should be able to use a query similar to this in SQL Server Management Studio (SSMS), add a where clause as needed (probably the uidGUID column, but I didn’t test it yet).

use BizTalkMgmtDb
select * from bts_receiveport 
where uidGUID = '794CD17E-6A4A-494C-BB30-564D323FD4D6'
--Substitute your GUID from the previous screen shot
--My Guid doesn't match above (B746...), 
-- because I fixed the Orchestration Binding 
-- before taking this second screen shot.