BizTalk Property Promotion

Property Promotion:

Property Promotion in BizTalk is usually about taking values from incoming message and moving them into the context of the message, so they are easily accessible and usable for routing. The context of message is a set of metadata about a message that resides in the message box with the message, allowing different part of BizTalk to read in a small set of metadata instead of the entire message, in case a value from a message needed at run time.

Below are three options for Property Promotion:

  • Distinguished Field
  • Property Schema
  • XPath

Note: Only those fields can be promoted as distinguished field or Property schema which occur only once in the message.

Following error will happen when promoting a value that can occur multiple times

Error.jpg

Distinguished Fields Property Schema
These field are excellent and fast way to both accessing and writing values to and from in Orchestration Only Promoted Property can have used for message routing, correlations and can be used in orchestrations
These fields are restricted to contains values that comes from some element (that can occur only once) It can contain data that is purely metadata about the message
Do not participate in routing
IsPromoted = false
Only promoted property can be used for tracking purposes with the build-in tracking functionality
Do not have a size limitation They are restricted to 256 characters
Do not require the creation of a corresponding property schema Create a separately maintained property schema
They are not persisted to the Message Box database. Instead, they are essentially XPath aliases, which simply point to the appropriate XML data field. Promoted properties are persisted to the Message box database. The Message box generate a large join in SQL Server each time a message is published, which is basically a join between the Context of Message, the possible properties, and the properties of all subscribers. So the no. of Promoted Properties should be keep minimum
Use in Orchestration as below:

MessageName.RecordName.FieldName

Use in Orchestration as below:

MessageName(
PropertySchemaName.PromotedPropertyName)

Distinguished field through the BizTalk API:

pInMsg.Context.Write(“theDistinguishedProperty”,
“http://schemas.microsoft.com/BizTalk/2003/btsDistinguishedFields”,
“theDistinguishedValue”);

Promote properties through the BizTalk API:

message.Context.Promote(“MessageType”, “http://schemas.microsoft.com/BizTalk/2003/system-properties”, messageType);

XPath:

XPath is much slower than Promoted Property and Distinguished Field. XPath function requires the Orchestration Engine to load the entire message into the memory to evaluate the XPath expression.

XPath should only use for getting and setting value of element that are recurring where Promoted Property and Distinguished field can not helpful.

 

 

Advertisements

Using Dictionary for BizTalk Instances

Sometimes in BizTalk, we may need to use Dictionary for checking various conditions for multiple messages/Records of the same BizTalk Instance. This can be achieved using Dictionary ThreadStaticAttribute.

Requirement: My BizTalk Orchestration accepts envelop message (Multiple records), I need to loop through each record and insert the data in sql table. Here the condition is I should not insert duplicate records in the table as my envelope message might have duplicate records. So, in orchestration before sql insert, I need to check whether the record is already inserted.

This requirement can be achieved using Dictionary ThreadStaticAttribute.

ThreadStatic variable is scoped to the current thread that is being processed.

We need to call a .net component from BizTalk expression shape by sending Key and Value pair as input parameters.

 

Dictionary.png

 

//SampleLookup is variable name which points to the class “LookUpHelper”

//Lookup is the name of the method which is accepting two parameters.

// lookupResult is Boolen variable.

//Key, Value is some unique identification for the record, example PolicyId/BrokerId…

 

Below .net component has a method “Lookup” which accepts two input parameters and return Boolean.

  • If the record exists in Dictionary, method will return “true”.
  • If the record doesn’t exist in Dictionary, method will insert the data into Dictionary and return “false”.
  • In Orchestration, If the method return value is “true”, you can skip sql insertion.
  • If the method return value is “false”, you can proceed for sql insertion.

You need to call the lookup method for each record in loop shape.

//.Net Code

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace SampleNamespace

{

    [Serializable]

    public class LookUpHelper

    {

        //Create Dictionary

        [System.ThreadStaticAttribute]

        private static System.Collections.Generic.Dictionary<string, string> _data = new System.Collections.Generic.Dictionary<string, string>();

        public static System.Collections.Generic.Dictionary<string, string> Data

        {

            get

            {

                if (_data == null)

                {

                    _data = new System.Collections.Generic.Dictionary<string, string>();

                }

                return _data;

            }

            set

            {

                _data = value;

            }

        }

            /// <summary>

        /// Method to check if the value is already present and if not, store the value in dictionary against a key

        /// </summary>

        /// <param name=”key”>key</param>

        /// <param name=”value”>value</param>

        public Boolean Lookup(string key, string value)

        {

            if (Data.ContainsKey(key))

            {              

                return true;

            }

            else

            {               

                Data.Add(key, value);

                return false;

            }

        }

    }

}

BizTalk Supporting Tools

There are available several BizTalk supporting tool available which will helpful for developing, Support and performance optimization on BizTalk applications. Below are some important supporting tools and their download locations.

1. BTDF (BizTalk deployment Framework)

BizTalk Deployment Framework is a third-party tool used to automate the BizTalk deployment process. Main advantage of using this tool is to generate the bindings automatically for various environments. We create msi file in local environment by following BTDF steps and deploy the msi in target machine by selecting appropriate binding file in the deployment wizard.

You can download this tool from below reference.

https://marketplace.visualstudio.com/items?itemName=DeployFxForBizTalkTeam.DeploymentFrameworkforBizTalkToolsforVS2015

https://marketplace.visualstudio.com/items?itemName=DeployFxForBizTalkTeam.DeploymentFrameworkforBizTalk

https://github.com/BTDF/DeploymentFramework

Top Reasons to Use the Deployment Framework for BizTalk

  • Deploy a complex solution containing orchestrations, schemas, maps, rules, custom components, pipeline components, pipelines — even ESB itineraries — in minutes, with no human intervention
  • Eliminate manual steps in your BizTalk deployments
  • Consolidate all your environment-specific configuration and runtime settings into one, easy-to-use Excel spreadsheet
  • Maintain a single binding file that works for all deployment environments
  • Make automated deployment a native part of the BizTalk development cycle, then use the same script to deploy to your servers
  • Use your build server to produce ready-to-deploy MSI installer

2. BizTalkHealthMonitor:

BizTalk health monitoring tool is available from BizTalk 2013 R2 and above version. This tool is exist in C:\Program Files (x86)\Microsoft BizTalk Server 2013 R2\SDK\Utilities\Support Tools location. When you install the BizTalk Server.

This tool helps you easily monitor the health of your BizTalk environment. BHM is based on the same engine as MBV. This snap-in can be added to the existing BizTalk Administration Console or can be run individually in its own MMC window.

 Following are the major features of BHM:

  • Monitor Multiple BizTalk Environments
  • Generate and View MBV reports
  • Dashboard view for overall health of BizTalk Environments
  • Schedule Report Collection
  • Send Email Notifications
  • Performance Monitor integration with pre-loaded scenario-based Performance counters
  • Report Management

    3. MsgBoxViewer:

BizTalk provides Message Box Viewer (MBV) tool out of box to generate report for BizTalk health and performance monitoring activity. It’s collecting details about BizTalk Server, Configuration, database and performance details.

MBV analyze in details of BizTalk MsgBox Db but also other BizTalk Dbs and generates an HTML file containing different REPORTS including a “WARNINGS REPORT” which report in yellow and red some warnings.

This tool comes along with BizTalk. When we installed BizTalk, this will available at below location:

C:\Program Files (x86)\Microsoft BizTalk Server 2013\SDK\Utilities\Support Tools\MsgBoxViewer

click here to get more details :

https://vkbiztalk.com/2018/02/15/biztalk-health-monitoring-and-message-box-viewer/

4. BizTalk Terminator tool

The BizTalk Terminator tool allows the you to easily address common BizTalk issues via SQL, WMI, and PowerShell based tasks provided by the BizTalk team. with additional functionality including the ability to suspend, resume, and terminate in bulk by date range as well as make performance tuning changes. Integration with mbvcleanupscripts.xml from the MessageBox Viewer Utility allows Terminator to quickly resolve issues identified by MBV.

For more details click here.

you can download this tool from below link:

https://www.microsoft.com/en-in/download/details.aspx?id=2846

5. BizTalk Assembly Checker

After BizTalk applications deployment in single and multiple environment. When we need to check and verify about all the dlls are deployed properly and also save their reference in BizTalK management Database. This tool provide all the details on single click.

Use the BizTalk Assembly Checker and Remote GAC tool (BTSAssemblyChecker.exe) to check the versions of assemblies deployed to the BizTalk Management database and to verify that they are correctly registered in the GAC on all BizTalk Server computers.

C:\Program Files (x86)\Microsoft BizTalk Server 2013 R2\SDK\Utilities\Support Tools\BiztalkAssemblyChecker

6. BizTalk Documenter:

This tool provides all the details of BizTalk applications in documents. This tool is helpful when we need to share the details and creating documents.

BizTalkDocument.jpg

You can download this tool from below website:

https://github.com/mbrimble/biztalkdocumenter

 

 

 

 

Types Of BizTalk Deployment

Using this blog, I just want to throw some light on different ways of BizTalk deployments.

Manual Deployment: This is pretty known style of BizTalk deployment by exporting MSI, Binding files from local environment and import the same in target environment. Here is some of the steps need to be followed.

  • Export MSI from Local Environment
  • Export BindingFile from Local environment
  • Open BidningFile and edit required details like Sendport/Receiveport locations…
  • After edit, just save the Binding file
  • Stop the application in Target Environment
  • Stop Host Instances in Target Environment
  • Import MSI in Target Environment
  • Import Binding file in Target Environment
  • Start Host instances
  • Start BizTalk Application.

Deployment using PowerShell Scripting: This style avoids some of the manual steps mentioned above. Here we write PowerShell commands for all deployment steps and execute the scripts in Target machine.

BTDF Deployment:

BizTalk Deployment Framework is a third-party tool used to automate the BizTalk deployment process. Main advantage of using this tool is to generate the bindings automatically for various environments. We create msi file in local environment by following BTDF steps and deploy the msi in target machine by selecting appropriate binding file in the deployment wizard.

Continuous Integration & Continuous Deployment (Dev Ops):

Continuous Integration approach is most advanced and effective deployment process in BizTalk. We need to use couple of tools (BTDF, TFS, Teamcity, MyGet and Octopus) to setup this process. Here is the sequence of steps we need to follow to setup this process.

  • When ever you do some code changes, you need to check in the code to TFS
  • TeamCity is a tool, which keep monitor for any TFS Checkins.
  • If any TFS checkins found, it will take the latest code from TFS, build it and deploy to Teamcity local environment.
  • If deployment is successful, it will create a Build and place into MyGet Server (This is used to maintain proper versions for Builds).
  • Octopus is a third-party tool using which we deploy the BizTalk artifacts to target environments.
  • In Octopus we need to do couple of configuration to connect MyGet Server, Target Environments.
  • We need to write deployment steps using powershell scripting in Octopus.
  • We create a BizTalk release in Octopus by selecting latest Build from MyGet server.
  • While deploying we need to select the target machine in drop down list and deploy it.
  • Using Powershell scripting steps, BizTalk code will be deployed to Target machine.

Add Http Headers For WCF/Rest Services

Requirement: There is a BizTalk service exposed as a Request and Response Rest service. I need to pass message to that Rest service with some http headers. BizTalk service has to receive those headers and pass it to back end service.

How to send headers to BizTalk Rest Service From third party tools like Postman.

httpheaders1.png

In BizTalk Orchestration message assignment shape, we need to assign incoming message context properties to another message which we are sending to request and response logical port.

Message2(*) = Message1(*) 

In order to populate http headers in the message which is sending to destination system, we need to assign some properties at behaviour section of sendport.

Please follow steps below.

  1. we need to create a class library with below code, build it and Gac it.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Xml;

using System.ServiceModel.Configuration;

using System.ServiceModel.Description;

using System.ServiceModel.Dispatcher;

using System.ServiceModel.Channels;

using System.ServiceModel;

using System.Configuration;

namespace AppName.CustomBehaviors

{

    public class AddHttpHeaderInspector : IDispatchMessageInspector, IClientMessageInspector

    {      

        private const string Source = “AddHttpHeaderContextInspector”;

        private const string contextHttpHeaderNS = @”http://schemas.microsoft.com/BizTalk/2006/01/Adapters/WCF-properties&#8221;;

        private const string contextHttpHeaderName = “HttpHeaders”;

        private const string httpResponseMessagePropertyName = “httpResponse”;

       private string headerFields;       

        public string HeaderFields    

    {

            get

            {

                return headerFields;

            }

            set

            {

                headerFields = value;

            }

        }

        public AddHttpHeaderInspector(string httpHeaders)

        {

            this.HeaderFields = httpHeaders;

        }

        public AddHttpHeaderInspector()

        {

        }

        public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)

        {

        }

        public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)

        {

            //Adds any headers in the WCF.HttpHeaders context property to the HTTP Headers

            //expects headers in the form “Header1: Value1, Header2: Value2”

            const string httpHeadersKey = “http://schemas.microsoft.com/BizTalk/2003/file-properties#ReceivedFileName&#8221;;

            if (request.Properties.ContainsKey(httpHeadersKey))

            {

                Dictionary<string, string> httpHeadersContext = GetHttpHeadersContext(Convert.ToString(request.Properties[httpHeadersKey]));

                HttpRequestMessageProperty httpRequestMessage;

                object httpRequestMessageObject;

                if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject))

                {

                    httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;

                }

                else

                {

                    httpRequestMessage = new HttpRequestMessageProperty();

                    request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);

                }

                string[] hdrs = HeaderFields.Split(new char[] { ‘,’ }, StringSplitOptions.RemoveEmptyEntries);

                foreach (string hdr in hdrs)

                {

                    String[] fixedHdr = hdr.Split(new char[] { ‘:’ }, StringSplitOptions.RemoveEmptyEntries);

                    if (fixedHdr.Length > 1)

                    {

                        httpRequestMessage.Headers[fixedHdr[0]] = fixedHdr[1];

                    }

                    else

                    {

                        if (httpHeadersContext.ContainsKey(fixedHdr[0]))

                        {

                            httpRequestMessage.Headers[fixedHdr[0]] = httpHeadersContext[fixedHdr[0]];

                        }

                    }

                }

            }

            return null;

        }        

   

        public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)

        {

            return null;

        }

        public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)

        {

            try

            {

                object objContextHttpHeaders;

                object objHttpResponse;

                HttpResponseMessageProperty httpResponseMessage;

 

                if (reply.Properties.TryGetValue(string.Format(“{0}#{1}”, contextHttpHeaderNS, contextHttpHeaderName), out objContextHttpHeaders))

                {

                    Dictionary<string, string> httpHeadersContext = GetHttpHeadersContext(Convert.ToString(objContextHttpHeaders));

                      //Dictionary<string, string> subhttpHeadersContext = null;

                    if (reply.Properties.TryGetValue(httpResponseMessagePropertyName, out objHttpResponse))

                    {

                        if (objHttpResponse == null)

                        {

                            httpResponseMessage = new HttpResponseMessageProperty();

                            AddHttpHeaderContextToResponseHeaders(httpHeadersContext, httpResponseMessage);

                            reply.Properties.Add(httpResponseMessagePropertyName, httpResponseMessage);

                        }

                        else

                        {

                            httpResponseMessage = objHttpResponse as HttpResponseMessageProperty;

                            httpResponseMessage.Headers.Clear();

                            string[] hdrs = HeaderFields.Split(new char[] { ‘,’ }, StringSplitOptions.RemoveEmptyEntries);

                            foreach (string hdr in hdrs)

                            {

                                String[] fixedHdr = hdr.Split(new char[] { ‘:’ }, StringSplitOptions.RemoveEmptyEntries);

                                if (fixedHdr.Length > 1)

                                {

                                    httpResponseMessage.Headers[fixedHdr[0]] = fixedHdr[1];

                                }

                                else

                                {

                                    if (httpHeadersContext.ContainsKey(fixedHdr[0]))

                                    {

                                        httpResponseMessage.Headers[fixedHdr[0]] = httpHeadersContext[fixedHdr[0]];

                                    }

                                }

                            }

                        }

                    }

                }

            }

            catch (Exception ex)

            {

               throw;

            }

        }

        private Dictionary<string, string> GetHttpHeadersContext(string rawHttpHeaders)

        {

            Dictionary<string, string> headersDictionary = new Dictionary<string, string>();

            string[] headerlines = rawHttpHeaders.Split(new char[] {‘\n’, ‘\r’}, StringSplitOptions.RemoveEmptyEntries);

            foreach (string headerline in headerlines)

            {

                string[] headerfields = headerline.Split(new char[]{‘:’}, StringSplitOptions.RemoveEmptyEntries);

                if (headerfields.Length > 1)

                {

                    headersDictionary.Add(headerfields[0], headerfields[1]);

                }

            }

            return headersDictionary;

        }

        private void AddHttpHeaderContextToResponseHeaders(Dictionary<string, string> httpHeadersContext, HttpResponseMessageProperty httpResponseMessage)

        {

            foreach (string headerName in httpHeadersContext.Keys)

            {

                httpResponseMessage.Headers.Add(headerName, httpHeadersContext[headerName]);

            }

        }

    } 

 

    public class AddHttpHeaderBehavior : IEndpointBehavior

    {

        private string headerFields;       

        public string HeaderFields

        {

            get

            {

                return headerFields;

            }

            set

            {

                headerFields = value;

            }

        }

        public AddHttpHeaderBehavior(string httpHeaders)

        {

            this.HeaderFields = httpHeaders;

        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)

        {

            AddHttpHeaderInspector inspector = new AddHttpHeaderInspector(HeaderFields);

            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);

        }

        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)

        {

            return;

        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)

        {

            AddHttpHeaderInspector headerInspector = new AddHttpHeaderInspector(HeaderFields);

            clientRuntime.MessageInspectors.Add(headerInspector);

         }

       

        public void Validate(ServiceEndpoint endpoint)

        {

            return;

        }

    }

 

    public class AddHttpHeaderBehaviorExtensionElement : BehaviorExtensionElement

    {

        [ConfigurationProperty(“HeaderFields”, DefaultValue = “”, IsRequired = false)]

        public string HeaderFields

        {

            get { return (string)base[“HeaderFields”]; }

            set { base[“HeaderFields”] = value; }

        }

 

        protected override object CreateBehavior()

        {

            return new AddHttpHeaderBehavior(HeaderFields);

        }

 

        public override Type BehaviorType

        {

            get { return typeof(AddHttpHeaderBehavior); }

        }

    }

}

2) Mention fully qualified name of the above dll in the Machine.config like below.

We have to include below configuration entry in behaviorExtensions within machine.config file located in below mentioned folders.

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\

C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\

       <add name=”AddHttpHeader” type=”AppName.CustomBehaviors.AddHttpHeaderBehaviorExtensionElement, AppName.CustomBehaviors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXXXXXX”/>

3) In send port, we need to apply EndpointBehaviors under Behavior tab and mention the header field names like below.

 

httpheaders2.png

Now you will be able to send the HttpHeaders along with outgoing message.

BizTalk Dynamic Send Ports For Rest Services

Dynamic send ports are used to send the BizTalk messages dynamically from orchestration to destination systems based on some conditions.

There are two types of dynamic send ports.

  • One-way dynamic Send Port:

Using one-way dynamic send port, we just send the messages to destination systems, but don’t expect the response back.

We need to create a logical send port in orchestration with port direction as Dynamic.

OneWayDynamic1.png

In the expression shape, we need to specify the destination location and Transport Type properties.

OneWayDynamic2.png

OneWayDynamic3.png

In Expression_1, you need to write below code

Port_Dynamic(Microsoft.XLANGs.BaseTypes.Address)=@”file://D:\Test1″;

Port_Dynamic(Microsoft.XLANGs.BaseTypes.TransportType)=”FILE”;

//Port-Dynamic is the Dynamic send port name.

//In Expression_2, you need to write below code

Port_Dynamic(Microsoft.XLANGs.BaseTypes.Address)=@”file://D:\Test2″;

Port_Dynamic(Microsoft.XLANGs.BaseTypes.TransportType)=”FILE”;

  • Two Way Dynamic Send Port

Two-way dynamic sendports are used for request and response messages.

We need to create logical dynamic sendport with port direction as dynamic.

TwoWayDynamic1.png

We need to construct the message with all request and response message properties of Rest endpoint as below

In the message assignment shape we need to construct the message with below properties.

RequestForRouting = Request;

//Request is the input message type of your orchestration receive shape. RequestForRouting is the message which we construct in this message assignment shape.

RequestForRouting(BTS.RouteDirectToTP)=false;

headerhttp = Request(WCF.InboundHttpHeaders);//If you have any http headers

RequestForRouting(FILE.ReceivedFileName) = headerhttp;

RequestForRouting(WCF.HttpMethodAndUrl) = “POST” //For POST Operation

RequestForRouting(WCF.HttpMethodAndUrl)=”<BtsHttpUrlMapping><Operation Name=” Method=’GET’ Url=’/RestServiceURL’ /></BtsHttpUrlMapping>”; // For Get Operation

RequestForRouting(BTS.SendPipelineConfig)=”<Root xmlns:xsd=’http://www.w3.org/2001/XMLSchema&#8217; xmlns:xsi=’http://www.w3.org/2001/XMLSchema-instance’><Stages><Stage CategoryId=’9d0e4108-4cce-4536-83fa-4a5040674ad6′><Components><Component Name=’Microsoft.BizTalk.Component.JsonEncoder’><Properties><RemoveOuterEnvelope vt=’11’>-1</RemoveOuterEnvelope></Properties></Component></Components></Stage></Stages></Root>”;

RequestForRouting(BTS.SendPipelineResponseConfig) = “<Root xmlns:xsd=’http://www.w3.org/2001/XMLSchema&#8217; xmlns:xsi=’http://www.w3.org/2001/XMLSchema-instance’><Stages><Stage CategoryId=’9d0e4103-4cce-4536-83fa-4a5040674ad6′><Components><Component Name=’Microsoft.BizTalk.Component.JsonDecoder’><Properties><RootNode vt=’8′>” + RootNodeName + “</RootNode><RootNodeNamespace vt=’8′>” + Namespace + “</RootNodeNamespace></Properties></Component><Component Name=’Microsoft.BizTalk.Component.XmlDasmComp’><Properties><AllowUnrecognizedMessage vt=’11’>-1</AllowUnrecognizedMessage></Properties></Component></Components></Stage></Stages></Root>”; 

RequestForRouting(WCF.VariablePropertyMapping)=String.Empty;

//For POST Operation

RequestForRouting(WCF.VariablePropertyMapping)=

“<BtsVariablePropertyMapping xmlns:xsi=’http://www.w3.org/2001/XMLSchema-instance&#8217; xmlns:xsd=’http://www.w3.org/2001/XMLSchema’><Variable Name=NameoftheVariable PropertyName=’NameOftheProperty‘ PropertyNamespace=’NameSpace‘/></BtsVariablePropertyMapping>”;

//For Get Operation

RequestForRouting(WCF.SuppressMessageBodyForHttpVerbs)=String.Empty;

//For POST Operation

RequestForRouting(WCF.SuppressMessageBodyForHttpVerbs)=”GET”;

//For Get Operation

RequestForRouting(BTS.RetryCount) = 0;

RequestForRouting(WCF.MaxReceivedMessageSize)=2147483647;

RequestForRouting(WCF.OpenTimeout)=”00:01:00″;

RequestForRouting(WCF.CloseTimeout)=”00:01:00″;

RequestForRouting(WCF.SendTimeout)= “00:01:00”;

RequestForRouting(WCF.EndpointBehaviorConfiguration)=”<behavior name=’EndpointBehavior’><AddHttpHeader HeaderFields=’Field1,Field2,Content-Type: application/json’/></behavior>”;

// If you have http headers

In the expression shape, we need to specify Address and TransportType.

TwoWayDynamic2.png

DynamicCommonSendPort(Microsoft.XLANGs.BaseTypes.Address)=”Rest Endpoint URL Name”;

DynamicCommonSendPort(Microsoft.XLANGs.BaseTypes.TransportType)=”WCF-WebHttp”;

Good Luck…

 

ESB Itinerary Samples

When we start working on itinerary then most of time we struggle with how to do development of ESB Itinerary and search out several blogs or website.

But we forgot that when ESB toolkit installs on BizTalk Server then Microsoft also provides several samples of How to use ESB itinerary in different conditions.

At C:\Program Files (x86)\Microsoft BizTalk ESB Toolkit location one ESBSource zip file is available.

You need to extract the zip file under C:\Projects folder, if not available then create this folder. And at below location you can get sample project GlobalBank.ESB.Samples.Itinerary at C:\Projects\ESBSource\Source\Samples\Itinerary location.

In this project there are defined several kinds of ESB Itinerary sample scenario. You can take help of this project to build or create new itinerary.

ESB Tracking Log:

When we are developing ESB Itinerary, then sometimes we are not able to reach out where exception occur in Itinerary. Debugview tool is provided by below website. You can download this tool and run that to get ESB log to track the ESB Itinerary Steps.

https://docs.microsoft.com/en-us/sysinternals/downloads/debugview

Also you need to do small addition in machine config file as below:

  1. openC:\Windows\Microsoft.NET\Framework\v4.0.30319\CONFIG\machine.config for 32-bit
    C:\Windows\Microsoft.NET\Framework64\v4.0.30319\CONFIG\machine.config for 64-bit
  2. Locate the line with the closing configSections tag.
  3. Under that line paste the following section:

<system.diagnostics>

        <switches>

          <add name=”BizTalkESBToolkit” value=”4″/>   

</switches>

</system.diagnostics>

4. Save and close machine.config.

5. In DebugView, on the Capture menu, click Capture Global Win32 to make sure that            it is checked.

6. Restart the BizTalk host instances.

Below are some links where you can get more information about Itinerary details:

ESB With WCF-SQL:

http://geekswithblogs.net/paulp/archive/2011/09/28/147087.aspx

http://www.biztalkgurus.com/blogs/msft-biztalk-community/esb-off-ramp-with-dynamic-resolver-to-wcf-sql-binding

ESB Request Response:

https://www.biztalk-server-tutorial.com/2014/12/18/part-2-itineraries-with-two-way-calls/

ESB For multiple Subscriber:

https://social.technet.microsoft.com/wiki/contents/articles/17965.biztalk-server-implementation-of-routing-slip-pattern-using-esb-toolkit-2-1.aspx

ESB Wiki

https://social.technet.microsoft.com/wiki/contents/articles/7756.biztalk-server-esb-survival-guide.aspx

https://social.technet.microsoft.com/wiki/contents/articles/17006.understanding-biztalk-esb-toolkit.aspx

 

 

 

 

 

Dynamic maps in BizTalk Orchestration

Requirement: I need to expose a BizTalk Rest service with multiple Verbs (Get/Post/Update) to front end system. When front end system calls BizTalk Rest service, for each Operation (Get/Post/Update) I need to construct request message to send to backend system and get the response back and need to construct response map and send the response back to Front End.

Solution1: For each operation I need to construct 2 maps (Request and Response) and 1 Orchestration, if I have 10 Get operations, I need to create 10 Orchestrations.

Solution2: Using BizTalk dynamic Maps concept, we can use single orchestration to call the maps dynamically from Orchestration.

We need to follow below steps in orchestration.

  • After receiving the message using Receive shape, we need to take an expression shape to extract the Operation name and assign to a string variable.

Expression Shape:

DynamicMaps1.jpg

Operation = RequestMessage(BTS.Operation);

//Operation is a string variable

//RequestMessage is the message type of receive shape.

//BTS.Operation is the context property and this value will be assigned in the Receive location for each operation.

// Pass the Operation name (which is extracted above) as input parameter to a C# component to get fully qualified request Map name.

requestMapName = varGetMapName.GetRequestMapName(Operation);

//requestMapName is a string variable

//varGetMapName is a variable of type C# Class where we have GetRequestMapName method.

  • Take Message Assignment Shape and write below code

DynamicMaps2.jpg

 mapType = System.Type.GetType(requestMapName);

transform(QueryRequest) = mapType(EnquiryRequest);

//mapType is a variable of type “System.Type”

// EnquiryRequest is a message which we receive in Receive Shape

// QueryRequest is a message which we construct (Backend system request message)

  • Take Send shape to send the above constructed message to Backend system through logical request and response port.
  • Take the Receive shape to get the backend system response.
  • Take Expression shape and write below code

DynamicMaps3.jpg

ResponseMapName = varGetMapName.GetResponseMapName(Operation);

//ResponseMapName is a string variable

//varGetMapName is a variable of type C# Class where we have GetResponseMapName method.

  • Take Message Assignment Shape and write below code.

DynamicMaps4.jpg

mapType = System.Type.GetType(responseMapName);

transform(EnquiryResponse) = mapType(QueryResponse);

//mapType is a variable of type “System.Type”

// EnquiryResponse is a message which we send to front end system.

// QueryResponse is a response message which we receive from Backend system

  • Send the above constructed response message to Front end system.

//C# method to get the Request Map name based on QueryType

public string GetRequestMapName(String QueryType)

        {

            string MapName = string.Empty;

            switch (QueryType)

            {

                case “Sample1”:

                    MapName = “BizTalk.Sample.InternalRequest, BizTalk.Sample.Maps, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4f9ac75c4a70e419”

                    break;

 case “Sample2”:

                    MapName = “Fully Qualified Map Name”

                    break;

 case “Sample3”:

                    MapName = “Fully Qualified Map Name”

                    break;

            }          

            return MapName;      

        }

//C# method to get the Response Map name based on QueryType

public string GetResponseMapName(String QueryType)

        {

            string MapName = string.Empty;

            switch (QueryType)

            {

                case “Sample1”:

                    MapName = “Fully Qualified Map Name”

                    break;

 case “Sample2”:

                    MapName = “Fully Qualified Map Name”

                    break;

 case “Sample3”:

                    MapName = “Fully Qualified Map Name”

                    break;

            }          

            return MapName;       

        }