locked
ESB - Options to update message data RRS feed

  • Question

  • We have an incoming message that passes through multiple itineraries. One of the things to do in each itinerary is to update the value of a specific node with a new GUID before passing it on to the next itinerary. What are the options available to achieve this? We use BRE resolver. Can we call a helper class to update the node value? Or Use a map? Or any other ways
    Wednesday, June 8, 2016 4:17 AM

Answers

  • Hi

    It would be possible if you have an existing itinerary step that calls an existing map via the Transformation service. In that case, you can simply add this extra field mapping link in the existing map. No need to change any of your itineraries. 

    Another option:

    If you don't have a transformation itinerary step, you can also do this in your routing itinerary step. Before setting the EndPoint properties in the Routing BRE Rule Action, call a custom BRE vocabulary that sets the XML field to the GUID value. This new BRE Vocabulary will be a wrapper for your custom .NET helper that takes the TypedXmlDocument as input, and sets the field with GUID appropriately -

    Refer this sample on how to set XML fields using .NET helpers from BRE Rule Actions. 


    Thanks Arindam





    Wednesday, June 8, 2016 5:55 AM
    Moderator
  • This should be your method signature for any helper method where you want to manipulate a message within BRE-

    public static void SetFieldValue(TypedXmlDocument envelope, string FieldName, string FieldValue)

    {

    //code to manipulate the input TypedXmlDocument object

    //the second and third parameters are optional

    }

    That's it. Note that you are not executing in the context of an orchestration where modifying a message is not allowed. This is same as manipulating an XmlDocument object in memory - hence the changes you make to the object in above helper method will be visible later on as well - you are just passing around the reference to the same in-memory object. 

    Wednesday, June 8, 2016 9:55 AM
    Moderator
  • Hi

    When you pass the message from BRE to your Helper class, note the parameter signature for the helper method-

    public static void AddNodeWithValue(Microsoft.RuleEngine.TypedXmlDocument document, string xpath, string nodeName, object nodeValue)

    TypedXmlDocument is basically an XMLDocument which can be accessed from TypedXmlDocument.Document property. Please refer the sample code in the link I shared. You may/may not need to pass the other method parameters. Fetch the XmlDocument from TypedXmlDocument and set the GUID value in the correct field using a XPATH expression.

    Note:

    First keep the method signature in helper to be of type TypedXmlDocument, and see if you can pass the BRE input message to the helper. If it doesn't work,  due to incompatibility between TypedXmlDocument and ResolveProviderMessage, change the input parameter in your helper to be of type ResolveProviderMessage. You have to fetch the XmlDocument from within it in the method. Give this a go, it should ideally work.

    Bit of history on ResolveProviderMessage - really bit of a hindrance in most cases.


    Thanks Arindam



    Wednesday, June 8, 2016 7:53 AM
    Moderator

All replies

  • Hi

    You have plenty of options. The out-of-the-box way to do this would be to do this via a Transformation itinerary step. You can have a map that simply creates a new GUID value in a custom C# scripting functoid, and assigns that to your required destination element. The C# code in the functoid can be-

    public string getGUID()
    {
    	return System.Guid.NewGuid().ToString();
    }

    Note that if you already have an existing transformation itinerary step in the itinerary, you can add the above scripting functoid to the existing map. If not, add an additional transformation itinerary step with a map that creates the GUID field as noted above.


    Thanks Arindam



    Wednesday, June 8, 2016 5:28 AM
    Moderator
  • Thanks.

    Because these itineraries are already existing, I'm trying to minimize the changes (if possible avoid adding extra step in itinerary). In one of the existing steps, is there a way we can call a helper function to achieve this? 

    Wednesday, June 8, 2016 5:48 AM
  • Hi

    It would be possible if you have an existing itinerary step that calls an existing map via the Transformation service. In that case, you can simply add this extra field mapping link in the existing map. No need to change any of your itineraries. 

    Another option:

    If you don't have a transformation itinerary step, you can also do this in your routing itinerary step. Before setting the EndPoint properties in the Routing BRE Rule Action, call a custom BRE vocabulary that sets the XML field to the GUID value. This new BRE Vocabulary will be a wrapper for your custom .NET helper that takes the TypedXmlDocument as input, and sets the field with GUID appropriately -

    Refer this sample on how to set XML fields using .NET helpers from BRE Rule Actions. 


    Thanks Arindam





    Wednesday, June 8, 2016 5:55 AM
    Moderator
  • Thanks, the first option in the sample seems to be useful here. 

    The sample sets a node (PaperSize) value to 'Letter' where PaperSize is a vocabulary. In my case, the message would be 'Microsoft.Practices.ESB.ResolveProviderMessage'

    How to set the node value here?

    Wednesday, June 8, 2016 7:44 AM
  • Hi

    When you pass the message from BRE to your Helper class, note the parameter signature for the helper method-

    public static void AddNodeWithValue(Microsoft.RuleEngine.TypedXmlDocument document, string xpath, string nodeName, object nodeValue)

    TypedXmlDocument is basically an XMLDocument which can be accessed from TypedXmlDocument.Document property. Please refer the sample code in the link I shared. You may/may not need to pass the other method parameters. Fetch the XmlDocument from TypedXmlDocument and set the GUID value in the correct field using a XPATH expression.

    Note:

    First keep the method signature in helper to be of type TypedXmlDocument, and see if you can pass the BRE input message to the helper. If it doesn't work,  due to incompatibility between TypedXmlDocument and ResolveProviderMessage, change the input parameter in your helper to be of type ResolveProviderMessage. You have to fetch the XmlDocument from within it in the method. Give this a go, it should ideally work.

    Bit of history on ResolveProviderMessage - really bit of a hindrance in most cases.


    Thanks Arindam



    Wednesday, June 8, 2016 7:53 AM
    Moderator
  • Hi,

    You can do this using the Message Type check on each Itinerary call on Actions you can call your own Vocabulary which will set the NEW GUID to the field which you want.

    Hope this Helps!!!

    Please Mark as Answered if you satisfy with Reply.

    Wednesday, June 8, 2016 8:05 AM
  • When I use a helper method and call it from BRE

    public static void UpdateMyNodeValue(Microsoft.RuleEngine.TypedXmlDocument document, string xpath, string nodeName, stringnodeValue)

    Does it update the original message? Isn't it just updating a copy of the message?


    • Edited by adit19 Wednesday, June 8, 2016 9:43 AM
    Wednesday, June 8, 2016 9:40 AM
  • Microsoft.RuleEngine.XmlHelper has a method AddNodeWithValue which I believe adds a new node but what I am looking for is a method that updates the value of an existing node. 

    I wrote this custom method - UpdateMyNodeValue(Microsoft.RuleEngine.TypedXmlDocument document, string xpath, string nodeName, stringnodeValue) but we are not returning the updated message here. Am I missing somethnig here?

    Wednesday, June 8, 2016 9:53 AM
  • This should be your method signature for any helper method where you want to manipulate a message within BRE-

    public static void SetFieldValue(TypedXmlDocument envelope, string FieldName, string FieldValue)

    {

    //code to manipulate the input TypedXmlDocument object

    //the second and third parameters are optional

    }

    That's it. Note that you are not executing in the context of an orchestration where modifying a message is not allowed. This is same as manipulating an XmlDocument object in memory - hence the changes you make to the object in above helper method will be visible later on as well - you are just passing around the reference to the same in-memory object. 

    Wednesday, June 8, 2016 9:55 AM
    Moderator
  • With parameter type TypedXmlDcument, it doesn't seem to be working. It says - "does not exist, is not accessible, or does not contain a signature matching the arguments provided" (runtime error)

    And I do not see "Microsoft.Practices.ESB.ResolveProviderMessage" in my helper class...but I can see Microsoft.Practices.ESB.Resolver.IResolveProvider.


    • Edited by adit19 Wednesday, June 8, 2016 1:20 PM
    Wednesday, June 8, 2016 1:19 PM
  • Hi 

    Microsoft.Practices.ESB.Resolver.IResolveProvider is a different type altogether. 

    I just reflected the codebase and confirmed that there is no type called Microsoft.Practices.ESB.ResolveProviderMessage. It's just a string - underlying type is TypedXmlDocument.

    How are you specifying the rule Action?

    Is there a vocabulary created for the input document? Can you share a screenshot of the Rule Action, and the Type for the input message from the Rules composer?


    Thanks Arindam



    Wednesday, June 8, 2016 1:29 PM
    Moderator
  • I'm currently trying a sample 

    I have created vocabulary (Update Node Value) for the helper method which has 4 params - typedXml, NodeName, Source and NodeValue


    Wednesday, June 8, 2016 1:56 PM
  • Hi

    Create a vocabulary of 'XML Document Element or Attribute type' for the input XML document. Browse to the xsd  schema file that you will actually receive in the policy. Select the Root node of the schema as the for XPath Selector and finish - this type will be of TypedXmlDocument type-

    Now, for your Action, go to the newly Pubished vocabulary, drag the new Vocabulary you created beside the "Update Node Value" text.

    Similarly, in the actual ESB routing policy, when you create the new Action for updating the field, drag this new vocabulary type for the input message to the Action pane, so that it can be passed to your .NET helper.


    Thanks Arindam






    Wednesday, June 8, 2016 2:14 PM
    Moderator
  • It is working fine now, I think the issue was that I didn't stop the application before refreshing the dll containing the helper method

    When we pass a vocabulary of type "Microsoft.Practices.ESB.ResolveProviderMessage" from BRE and parameter type is "TypedXmlDocument" in helper method, it works.

    Thanks Arindam!

    Thursday, June 9, 2016 8:10 AM
  • Good to know :)

    Basically "Microsoft.Practices.ESB.ResolveProviderMessage" is not even a real class type -I reflected the codebase yesterday.

    It's just a hard-coded string in the ESB code for DocumentType property. Underlying type is still TypedXmlDocument.


    Thanks Arindam

    Thursday, June 9, 2016 8:17 AM
    Moderator
  • Hi Vikas,

    Your post has been flagged as abusive. Can you please let others decide whether a post is valuable or qualifies as an answer.

    Thank you.

    Steef-Jan Wiggers

    Microsoft Azure MVP


    BizTalk

    Saturday, June 18, 2016 3:33 PM
    Moderator
  • Hi Adit,

    I'm attempting to do the same thing as you however can't seem to have any luck.  I don't suppose you could share your code for your end solution?

    Heres' my forum post.

    https://social.msdn.microsoft.com/Forums/en-US/8cf1f4e2-5684-47dd-8acb-98f9cb760af4/updating-xml-element-in-bre-using-esb-routing-service?forum=biztalkgeneral

    Many thanks in advance


    GilesB

    Wednesday, June 22, 2016 12:04 PM