{"id":12110,"date":"2018-06-25T17:50:28","date_gmt":"2018-06-25T12:20:28","guid":{"rendered":"https:\/\/www.inogic.com\/blog\/?p=12110"},"modified":"2021-12-15T16:22:53","modified_gmt":"2021-12-15T10:52:53","slug":"parse-json-string-that-represents-the-dynamics-365-plugin-execution-context-received-in-azure-function","status":"publish","type":"post","link":"https:\/\/www.inogic.com\/blog\/2018\/06\/parse-json-string-that-represents-the-dynamics-365-plugin-execution-context-received-in-azure-function\/","title":{"rendered":"Parse JSON string that represents the Dynamics 365 plugin execution context received in Azure Function"},"content":{"rendered":"<h2><strong>Introduction:<\/strong><\/h2>\n<p style=\"text-align: justify;\">In our previous blogs of this <a href=\"http:\/\/bit.ly\/inogic-azurefunctions\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>Integrating Dynamics 365 with Azure Functions<\/strong><\/a> series, we have gone through a walkthrough with an example of creating an Azure Function and call the same through the following,<\/p>\n<ol style=\"text-align: justify;\">\n<li>An example of directly calling an Azure function from traditional workflows.<\/li>\n<li>Register as a WebHook and invoke it from a workflow.<\/li>\n<li>Register as a WebHook and register steps for messages that you would like the custom logic to be executed for.<\/li>\n<\/ol>\n<p style=\"text-align: justify;\">In this blog, we will illustrate how to parse the JSON data that we received in the Azure Function. Let\u2019s consider that we have registered a plugin step on an update of Account record which invoke a WebHook (here in our case Azure Function).<\/p>\n<ul>\n<li><strong>Read JSON data from the request body: <\/strong><\/li>\n<\/ul>\n<p style=\"text-align: justify;\">When plugin triggers and invokes a WebHook, three types of data received in the request i.e. Query String, Header Data and Request Body. The Request body contains a string that represents the JSON value of the <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/microsoft.xrm.sdk.remoteexecutioncontext.aspx\" target=\"_blank\" rel=\"noopener noreferrer\">RemoteExecutionContext<\/a> class. This class defines the contextual information sent to a remote service endpoint at run-time. Below code snippet reads the content from the <strong>HttpRequestMessage<\/strong> and converts the received JSON string to proper deserializable JSON string.<\/p>\n<pre class=\"lang:default decode:true \">using System.Text;\r\nusing System.Net;\r\n\r\npublic static async Task&lt;HttpResponseMessage&gt; Run(HttpRequestMessage req, TraceWriter log)\r\n{\r\nlog.Info(\"C# HTTP trigger function processed a request\");\r\n\r\n    string jsonContext = await req.Content.ReadAsStringAsync();\r\n    log.Info(\"Read context: \" + jsonContext);\r\n\r\n    jsonContext = FormatJson(jsonContext);\r\n    log.Info(\"Formatted JSON Context string: \" + jsonContext);\r\n\r\n    return req.CreateResponse(HttpStatusCode.OK, \"Success\");\r\n}\r\n\r\n\/\/\/ &lt;summary&gt;\r\n\/\/\/ Function to convert the unformatted Json string to formatted Json string\r\n\/\/\/ &lt;\/summary&gt;\r\n\/\/\/ &lt;param name=\"unformattedJson\"&gt;&lt;\/param&gt;\r\n\/\/\/ &lt;returns&gt;string formattedJsonString&lt;\/returns&gt;\r\npublic static string FormatJson(string unformattedJson)\r\n{\r\n    string formattedJson = string.Empty;\r\n    try\r\n    {\r\n        formattedJson = unformattedJson.Trim('\"');\r\n        formattedJson = System.Text.RegularExpressions.Regex.Unescape(formattedJson);\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n\r\n        throw new Exception(ex.Message);\r\n    }\r\n    return formattedJson;\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<blockquote><p>Remark: Add reference of System.Text so that we can use Regex expression.<\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<ul>\n<li><strong>Sample JSON string that gets received in the Azure Function:<\/strong><\/li>\n<\/ul>\n<p>Below is the sample JSON string.<\/p>\n<pre class=\"lang:default decode:true\">{\r\n  \"BusinessUnitId\": \"f0bf3c9a-8150-e811-a953-000d3af29fc0\",\r\n  \"CorrelationId\": \"39499111-e689-42a1-ae8a-5b14a84514ce\",\r\n  \"Depth\": 1,\r\n  \"InitiatingUserId\": \"df010dad-f103-4589-ba66-76a5a04c2a11\",\r\n  \"InputParameters\": [\r\n\r\n    {\r\n      \"key\": \"Target\",\r\n      \"value\": {\r\n        \"__type\": \"Entity:http:\\\/\\\/schemas.microsoft.com\\\/xrm\\\/2011\\\/Contracts\",\r\n        \"Attributes\": [\r\n          {\r\n            \"key\": \"telephone1\",\r\n            \"value\": \"1111\"\r\n          },\r\n          {\r\n            \"key\": \"accountid\",\r\n            \"value\": \"ec4e2f7d-9d60-e811-a95a-000d3af24950\"\r\n          },\r\n          {\r\n            \"key\": \"modifiedon\",\r\n            \"value\": \"\\\/Date(1527757524000)\\\/\"\r\n          },\r\n          {\r\n            \"key\": \"modifiedby\",\r\n            \"value\": {\r\n              \"__type\": \"EntityReference:http:\\\/\\\/schemas.microsoft.com\\\/xrm\\\/2011\\\/Contracts\",\r\n              \"Id\": \"df010dad-f103-4589-ba66-76a5a04c2a11\",\r\n              \"KeyAttributes\": [],\r\n              \"LogicalName\": \"systemuser\",\r\n              \"Name\": null,\r\n              \"RowVersion\": null\r\n            }\r\n          },\r\n          {\r\n            \"key\": \"modifiedonbehalfby\",\r\n            \"value\": null\r\n          }\r\n        ],\r\n        \"EntityState\": null,\r\n        \"FormattedValues\": [],\r\n        \"Id\": \"ec4e2f7d-9d60-e811-a95a-000d3af24950\",\r\n        \"KeyAttributes\": [],\r\n        \"LogicalName\": \"account\",\r\n        \"RelatedEntities\": [],\r\n        \"RowVersion\": null\r\n      }\r\n    }\r\n  ],\r\n  \"IsExecutingOffline\": false,\r\n  \"IsInTransaction\": true,\r\n  \"IsOfflinePlayback\": false,\r\n  \"IsolationMode\": 1,\r\n  \"MessageName\": \"Update\",\r\n  \"Mode\": 0,\r\n  \"OperationCreatedOn\": \"\\\/Date(1527757530151)\\\/\",\r\n  \"OperationId\": \"08fec203-ec78-4f7a-a024-c96e329a64fe\",\r\n  \"OrganizationId\": \"b0714265-8e72-4d3b-8239-ecf0970a3da6\",\r\n  \"OrganizationName\": \"org94971a24\",\r\n  \"OutputParameters\": [],\r\n  \"OwningExtension\": {\r\n    \"Id\": \"3db800fe-0963-e811-a95a-000d3af24324\",\r\n    \"KeyAttributes\": [],\r\n    \"LogicalName\": \"sdkmessageprocessingstep\",\r\n    \"Name\": \"D365WebHookHttpTrigger: Update of account\",\r\n    \"RowVersion\": null\r\n  },\r\n  \"ParentContext\": {\r\n    \"BusinessUnitId\": \"f0bf3c9a-8150-e811-a953-000d3af29fc0\",\r\n    \"CorrelationId\": \"39499111-e689-42a1-ae8a-5b14a84514ce\",\r\n    \"Depth\": 1,\r\n    \"InitiatingUserId\": \"df010dad-f103-4589-ba66-76a5a04c2a11\",\r\n    \"InputParameters\": [\r\n      {\r\n        \"key\": \"Target\",\r\n        \"value\": {\r\n          \"__type\": \"Entity:http:\\\/\\\/schemas.microsoft.com\\\/xrm\\\/2011\\\/Contracts\",\r\n          \"Attributes\": [\r\n            {\r\n              \"key\": \"telephone1\",\r\n              \"value\": \"1111\"\r\n            },\r\n            {\r\n              \"key\": \"accountid\",\r\n              \"value\": \"ec4e2f7d-9d60-e811-a95a-000d3af24950\"\r\n            }\r\n          ],\r\n          \"EntityState\": null,\r\n          \"FormattedValues\": [],\r\n          \"Id\": \"ec4e2f7d-9d60-e811-a95a-000d3af24950\",\r\n          \"KeyAttributes\": [],\r\n          \"LogicalName\": \"account\",\r\n          \"RelatedEntities\": [],\r\n          \"RowVersion\": null\r\n        }\r\n      },\r\n      {\r\n        \"key\": \"SuppressDuplicateDetection\",\r\n        \"value\": false\r\n      }\r\n    ],\r\n    \"IsExecutingOffline\": false,\r\n    \"IsInTransaction\": true,\r\n    \"IsOfflinePlayback\": false,\r\n    \"IsolationMode\": 1,\r\n    \"MessageName\": \"Update\",\r\n    \"Mode\": 0,\r\n    \"OperationCreatedOn\": \"\\\/Date(1527757524631)\\\/\",\r\n    \"OperationId\": \"08fec203-ec78-4f7a-a024-c96e329a64fe\",\r\n    \"OrganizationId\": \"b0714265-8e72-4d3b-8239-ecf0970a3da6\",\r\n    \"OrganizationName\": \"org94971a24\",\r\n    \"OutputParameters\": [],\r\n    \"OwningExtension\": {\r\n      \"Id\": \"63cdbb1b-ea3e-db11-86a7-000a3a5473e8\",\r\n      \"KeyAttributes\": [],\r\n      \"LogicalName\": \"sdkmessageprocessingstep\",\r\n      \"Name\": \"ObjectModel Implementation\",\r\n      \"RowVersion\": null\r\n    },\r\n    \"ParentContext\": null,\r\n    \"PostEntityImages\": [],\r\n    \"PreEntityImages\": [],\r\n    \"PrimaryEntityId\": \"ec4e2f7d-9d60-e811-a95a-000d3af24950\",\r\n    \"PrimaryEntityName\": \"account\",\r\n    \"RequestId\": \"08fec203-ec78-4f7a-a024-c96e329a64fe\",\r\n    \"SecondaryEntityName\": \"none\",\r\n    \"SharedVariables\": [\r\n      {\r\n        \"key\": \"ChangedEntityTypes\",\r\n        \"value\": [\r\n          {\r\n            \"__type\": \"KeyValuePairOfstringstring:#System.Collections.Generic\",\r\n            \"key\": \"account\",\r\n            \"value\": \"Update\"\r\n          }\r\n        ]\r\n      }\r\n    ],\r\n    \"Stage\": 30,\r\n    \"UserId\": \"df010dad-f103-4589-ba66-76a5a04c2a11\"\r\n  },\r\n  \"PostEntityImages\": [],\r\n  \"PreEntityImages\": [],\r\n  \"PrimaryEntityId\": \"ec4e2f7d-9d60-e811-a95a-000d3af24950\",\r\n  \"PrimaryEntityName\": \"account\",\r\n  \"RequestId\": \"08fec203-ec78-4f7a-a024-c96e329a64fe\",\r\n  \"SecondaryEntityName\": \"none\",\r\n  \"SharedVariables\": [],\r\n  \"Stage\": 40,\r\n  \"UserId\": \"df010dad-f103-4589-ba66-76a5a04c2a11\"\r\n\r\n}<\/pre>\n<ul>\n<li><strong>Parse JSON string to ExpandoObject dynamic object:<\/strong><\/li>\n<\/ul>\n<p>Below code snippet deserialize the JSON string to dynamic ExpandoObject.<\/p>\n<p>dynamic dynObj = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonContext);<\/p>\n<ul>\n<li><strong>Read values from dynamic object:<\/strong><\/li>\n<\/ul>\n<p>Simple string type,<\/p>\n<p>log.Info(&#8220;BusinessUnitId: &#8221; + dynObj[&#8220;BusinessUnitId&#8221;]);<\/p>\n<p><strong>or<\/strong><\/p>\n<p>log.Info(&#8220;BusinessUnitId: &#8221; + dynObj.BusinessUnitId);<\/p>\n<p>Complex ParameterCollection type,<\/p>\n<p>log.Info(&#8220;InputParameters-&gt;Target-&gt;LogicalName: &#8221; + dynObj[&#8220;InputParameters&#8221;][0][&#8220;value&#8221;][&#8220;LogicalName&#8221;].ToString());<\/p>\n<ul>\n<li><strong>Parse JSON string to RemoteExecutionContext object:<\/strong><\/li>\n<\/ul>\n<p>Below code snippet deserialize the JSON string to RemoteExecutionContext object<\/p>\n<pre class=\"lang:default decode:true\">#r \"bin\/Newtonsoft.Json.dll\"\r\n#r \"bin\/Microsoft.Xrm.Sdk.dll\"\r\n#r \"bin\/System.Runtime.Serialization.dll\"\r\n\r\nusing System.Net;\r\nusing System.Dynamic;\r\nusing System.Text;\r\npublic static async Task&lt;HttpResponseMessage&gt; Run(HttpRequestMessage req, TraceWriter log)\r\n{\r\n   string jsonContext = await req.Content.ReadAsStringAsync();\r\n   log.Info(\"Read context: \" + jsonContext);\r\n\r\n   jsonContext = FormatJson(jsonContext);\r\n   log.Info(\"Formatted JSON Context string: \" + jsonContext);\r\n\r\n   Microsoft.Xrm.Sdk.RemoteExecutionContext remoteExecutionContext = DeserializeJsonString&lt;Microsoft.Xrm.Sdk.RemoteExecutionContext&gt;(jsonContext);\r\n}\r\n\r\n\/\/\/ &lt;summary&gt;\r\n\/\/\/ Function to deserialize JSON string using DataContractJsonSerializer\r\n\/\/\/ &lt;\/summary&gt;\r\n\/\/\/ &lt;typeparam name=\"RemoteContextType\"&gt;RemoteContextType Generic Type&lt;\/typeparam&gt;\r\n\/\/\/ &lt;param name=\"jsonString\"&gt;string jsonString&lt;\/param&gt;\r\n\/\/\/ &lt;returns&gt;Generic RemoteContextType object&lt;\/returns&gt;\r\npublic static RemoteContextType DeserializeJsonString&lt;RemoteContextType&gt;(string jsonString)\r\n{\r\n    \/\/create an instance of generic type object\r\n    RemoteContextType obj = Activator.CreateInstance&lt;RemoteContextType&gt;();\r\n    MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString));\r\n    System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(obj.GetType());\r\n    obj = (RemoteContextType)serializer.ReadObject(ms);\r\n    ms.Close();\r\n    return obj;\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Remarks: <\/strong>Add reference of following dlls,<\/p>\n<ul>\n<li>Xrm.Sdk.dll<\/li>\n<li>Runtime.Serialization.dll<\/li>\n<\/ul>\n<ul>\n<li><strong>Read values from <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/microsoft.xrm.sdk.remoteexecutioncontext?view=dynamics-general-ce-9\" target=\"_blank\" rel=\"noopener noreferrer\">RemoteExecutionContext<\/a> class:<\/strong><\/li>\n<\/ul>\n<p>Below code snippet shows how to read values,<\/p>\n<pre class=\"lang:default decode:true\">\/\/read Plugin Message Name\r\n    string messageName = remoteExecutionContext.MessageName;\r\n    \/\/read execution depth of plugin\r\n    Int32 depth = remoteExecutionContext.Depth;\r\n    \/\/read BusinessUnitId\r\n    Guid businessUnitid = remoteExecutionContext.BusinessUnitId;\r\n    \/\/read Target Entity \r\n    Microsoft.Xrm.Sdk.Entity targetEntity = (Microsoft.Xrm.Sdk.Entity)remoteExecutionContext.InputParameters[\"Target\"];\r\n\r\n    \/\/read attribute from Target Entity\r\n    string phoneNumber = targetEntity.Attributes[\"telephone1\"].ToString();\r\n    log.Info(\"Message Name: \" + messageName);\r\n    log.Info(\"BusinessUnitId: \" + businessUnitid);\r\n    log.Info(\"Plugin Depth: \" + depth);\r\n\r\n    log.Info(\"TargetEntity Logical Name: \" + targetEntity.LogicalName);\r\n    log.Info(\"Phone Number: \" + phoneNumber);\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" class=\"aligncenter  wp-image-12111\" src=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2018\/06\/Parse-JSON.png\" alt=\"Parse JSON\" width=\"825\" height=\"419\" \/><\/p>\n<h2><strong>Conclusion:<\/strong><\/h2>\n<p style=\"text-align: justify;\">The steps given above describes how to Parse JSON string that represents the Dynamics 365 plugin execution context received in Azure Function. To read all blogs about Azure Functions visit: <a href=\"http:\/\/bit.ly\/inogic-azurefunctions\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/bit.ly\/inogic-azurefunctions<\/a><\/p>\n<h2 style=\"text-align: left;\"><div class=\"su-heading su-heading-style-default su-heading-align-center\" id=\"\" style=\"font-size:15px;margin-bottom:5px\"><div class=\"su-heading-inner\">Cut short 90% of your manual work and repetitive data entry!<\/div><\/div><\/h2>\n<p style=\"text-align: left;\"><em>Get 1 Click apps and say goodbye to all repetitive data entry in CRM &#8211;<\/em><br \/>\n<em><strong><a href=\"https:\/\/bit.ly\/3oH7dYw\" target=\"_blank\" rel=\"noopener noreferrer\">Click2Clone<\/a> <\/strong>\u2013 Clone\/Copy Dynamics 365 CRM records in 1 Click<\/em><br \/>\n<em><strong><a href=\"https:\/\/bit.ly\/3EPjAYc\" target=\"_blank\" rel=\"noopener noreferrer\">Click2Export<\/a><\/strong> \u2013 Export Dynamics 365 CRM Report\/CRM Views\/Word\/Excel template in 1 Click<\/em><br \/>\n<em><strong><a href=\"https:\/\/bit.ly\/3EN8h2v\" target=\"_blank\" rel=\"noopener noreferrer\">Click2Undo<\/a><\/strong> \u2013 Undo &amp; Restore Dynamics 365 CRM data in 1 Click<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction: In our previous blogs of this Integrating Dynamics 365 with Azure Functions series, we have gone through a walkthrough with an example of creating an Azure Function and call the same through the following, An example of directly calling an Azure function from traditional workflows. Register as a WebHook and invoke it from a\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.inogic.com\/blog\/2018\/06\/parse-json-string-that-represents-the-dynamics-365-plugin-execution-context-received-in-azure-function\/\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":13,"featured_media":12112,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[5,16,18,19],"tags":[185,186,568,1297],"class_list":["post-12110","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-functions","category-dynamics-365","category-dynamics-365-v9-2","category-dynamics-crm","tag-azure-function-dynamics-365","tag-azure-function-dynamics-crm","tag-dynamics-365-plugin-execution","tag-parse-json-string-dynamics-365"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/posts\/12110","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/comments?post=12110"}],"version-history":[{"count":0,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/posts\/12110\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/media\/12112"}],"wp:attachment":[{"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/media?parent=12110"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/categories?post=12110"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/tags?post=12110"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}