In the previous post, we saw how to invoke webhook using custom global action and passed plugin execution context to the webhook. In this last post of this series, we’ll see how to execute custom global action from JS on form load.

Using CRM Rest Builder, we can get the HttpRequest for executing action which is as below:

DXC.ExecuteAction = function (executionContext) {
    var formContext = executionContext.getFormContext();
    var globalContext = Xrm.Utility.getGlobalContext();

    var parameters = {};
    parameters.ServiceCeaseDate = new Date(2019, 5, 15);
    parameters.TargetEntity = formContext.data.entity.getEntityName();
    parameters.TargetID = formContext.data.entity.getId();

    var req = new XMLHttpRequest();
    req.open("POST", globalContext.getClientUrl() + "/api/data/v9.1/dxc_ACUpdateAccommodationPayments", true);
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.onreadystatechange = function () {
        if (this.readyState === 4) {
            req.onreadystatechange = null;
            if (this.status === 204) {
                //Success - No Return Data - Do Something
            } else {
                Xrm.Utility.alertDialog(this.statusText);
            }
        }
    };
    req.send(JSON.stringify(parameters));
};

We are passing the input parameters on Line 6-8 highlighted above. Once the action gets executed, webhook will be invoked and plugin context will be passed to it(as shown in the previous post) which in turn will be passed to the azure durable function.

So, we need to modify our durable function(shown in Part 3 of this series) a bit so that the plugin context that gets passed to the durable function in JSON format gets deserialized properly.

So, the code for HTTP triggered function is as shown below:

 [FunctionName("AccommodationPayments")]
        public static async Task


The logging at Line 8(highlighted above) will be helpful to show the plugin context passed to the durable function in JSON format as shown below:

{
	"BusinessUnitId": "1b4721fb-7058-e911-a959-000d3a3adab0",
	"CorrelationId": "e1ba9f97-c971-4979-b373-12a6a24ce74e",
	"Depth": 1,
	"InitiatingUserId": "02ae254c-335b-e911-a84c-000d3a3627b3",
	"InputParameters": [
		{
			"key": "ServiceCeaseDate",
			"value": "/Date(1571922000000)/"
		},
		{
			"key": "TargetEntity",
			"value": "contact"
		},
		{
			"key": "TargetID",
			"value": "{32B54F5A-95A6-E911-A857-000D3A372186}"
		},
		{
			"key": "parentExecutionId",
			"value": "b16df3e1-f2d9-45e9-a4f3-0db9048e28ac"
		}
	],
	"IsExecutingOffline": false,
	"IsInTransaction": true,
	"IsOfflinePlayback": false,
	"IsolationMode": 2,
	"MessageName": "dxc_ACUpdateAccommodationPayments",
	"Mode": 0,
	"OperationCreatedOn": "/Date(1572306594631)/",
	"OperationId": "82f1d96c-b623-4da9-ae44-d4d5e27249dd",
	"OrganizationId": "efe26240-1da4-4e7c-9c4e-c384e4868abc",
	"OrganizationName": "orgdb6bc5d5",
	"OutputParameters": [],
	"OwningExtension": {
		"Id": "c5640f2e-e6f6-e911-a862-000d3a372932",
		"KeyAttributes": [],
		"LogicalName": "sdkmessageprocessingstep",
		"Name": "Dxc.AgedCare.Crm.CorePlugins.ExecuteActionUpdateAccommodationPayments: dxc_ACUpdateAccommodationPayments of any Entity",
		"RowVersion": null
	},
	"ParentContext": null,
	"PostEntityImages": [],
	"PreEntityImages": [],
	"PrimaryEntityId": "00000000-0000-0000-0000-000000000000",
	"PrimaryEntityName": "none",
	"RequestId": "82f1d96c-b623-4da9-ae44-d4d5e27249dd",
	"SecondaryEntityName": "none",
	"SharedVariables": [
		{
			"key": "IsAutoTransact",
			"value": true
		}
	],
	"Stage": 40,
	"UserId": "02ae254c-335b-e911-a84c-000d3a3627b3"
}

The highlighted lines above show the data that we passed to the durable function through webhook. For deserialzing it we would need appropriate object to hold this data. http://json2csharp.com/ is one of the link which creates C# type based on the JSON data passed to it.

Hence, the converted C# types for the above JSON data are as shown below:

  public class InputParameter
    {
        public string key { get; set; }
        public string value { get; set; }
    }

    public class OwningExtension
    {
        public string Id { get; set; }
        public List


Then the Orchestration function code is as shown below:

 [FunctionName("AccommodationPayments_OrchestrationFunction")]
        public static async Task


The highlighted line above is responsible for deserializing the plugin context passed to durable function to InputContext object.

The code for Activity function is as shown below:

  [FunctionName("AccommodationPayments_ActivityFunction")]
        public static async Task


The helper method to get related records of contact record is as shown below:

 private static IEnumerable


Once done, let’s deploy the azure durable unction to Azure as shown in Part 3 of this series.

Before testing the entire functionality, let’s check the value of the records in the system which is as shown below:

After deploying the durable function to Azure, let’s test the code of calling custom global action on load of contact form(for demo purpose).
Once the global action is executed, the input parameters that are passed to it will be sent to webhook as part of plugin context when the webhook is invoked using custom global action.
Once the webhook is invoked, the plugin context will be passed to the azure durable function and will do further processing i.e. it will retrieve the related records of the contact record and will update their Expected Refund Due Date field.

Once the durable function is executed, we can check the status of the durable function and logging on Azure portal as shown in Part 3 of this series. After successful execution of durable function let’s see the value of the records back in D365 which is as shown below:

We can see that the date time value passed as input parameter has been reflected in Expected Refund Due Date.

So, in the final post of this series we saw how we can execute custom global action using JS based on any business requirement passing input parameters to it.

Hope it helps !!