Featured Post

Web API Requests Series

Web API Series:  Create and Retrieve , Update and Delete , Retrieve Multiple , Associate/Disassociate , Impersonation , Run Workflows

03 February 2017

Run Workflows using CRM 365 Web Api

Hi all, Today I am going to post a sample code you can use to run a workflow in CRM 365 using the new Web Api.

The function takes three parameters in input: the workflow Guid, the record Guid and a boolean to tell the Web Api whether or not to run the workflow synchronously; true = asynchronously which is the default behaviour, false = synchronously.
The Workflow should be set up to be run either as a child or On demand Workflow otherwise you'll get an error.

var _runWorkflow = function (workflowId, recordId) {

        var parameters = {};
        parameters.EntityId = recordId;

        var req = new XMLHttpRequest();
        req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v8.2/workflows(" + workflowId + ")/Microsoft.Dynamics.CRM.ExecuteWorkflow", false);
        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 === 200) {
                    var results = JSON.parse(this.response);
                } else {
                    //Xrm.Utility.alertDialog(this.statusText);
                }
            }
        };
        req.send(JSON.stringify(parameters));
    }

Here is an example of how to call the function above after saving the record via javascript:

Xrm.Page.data.save().then(
            function () {
                var entityType = Xrm.Page.data.entity.getEntityName();
                var recordId = Xrm.Page.data.entity.getId();

                var wfGuid = LDA.Functions.Common.GetWorkflowGuid(entityType);

                if (wfGuid == "na") return;

                LDA.Functions.Common.RunWorkflow(wfGuid, recordId.replace("}", "").replace("{", ""));
             
                Xrm.Page.data.refresh(false);
            },
            function () {
                //handle errors
            }
        );



That was it, very simple and straight forward, hope it helps to get you started with the new CRM 365 Web Api. If you have any questions leave a comment and I'll get back to you ASAP.

07 April 2016

Activities Timeline

I have recently been playing with a very nice HTML Timeline control and have integrated within the Account form in CRM using the new Web API, of course! The Timeline is used to display activities related to the current Account record, it could be used on any record type though.

Here is a screenshot of the beta version:

Some of the functionalities so far:
  • Add new activities (phone calls, emails, tasks, appointments)
  • Drag to reschedule activities
  • Select activities to display
  • Zoom in and out to adjust the period displayed
  • Refresh view
  • Go to Today's activities

04 March 2016

Web API Requests Series

Web API Series: Create and Retrieve, Update and Delete, Retrieve Multiple, Associate/Disassociate, Impersonation, Run Workflows

CRM 2016 - WEB API Operations - Associate/Disassociate for Many to Many

Associate and Disassociate for Many to Many (i.e. Collection-Valued navigation property) relationships using the new CRM 2016 Web API in Javascript.
In this example I am going to show you how to Associate/Disassociate two out of the box records: an opportunity and an account.
You can find more information about Single and Collection-Valued properties here and here

this.associateRecords = function (parentId, parentType, relationshipName, childId, childType, successCallback, errorCallback) {
        var req = new XMLHttpRequest();
        req.open("POST", encodeURI(getWebAPIPath() + parentType + "(" + parentId + ")/" + relationshipName + "/$ref"), true);
        req.setRequestHeader("Accept", "application/json");
        req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        req.setRequestHeader("OData-MaxVersion", "4.0");
        req.setRequestHeader("OData-Version", "4.0");
        req.onreadystatechange = function () {
            if (this.readyState == 4 /* complete */) {
                req.onreadystatechange = null;
                if (this.status == 204 || this.status == 1223) {
                    successCallback();
                }
                else {
                    errorCallback(bd_Utilities.WebAPI.errorHandler(this));
                }
            }
        };
        var childEntityReference = { "@odata.id": getWebAPIPath() + "/" + childType + "(" + childId + ")" };

        req.send(JSON.stringify(childEntityReference));  
    };

//Account: E48456EE-49B0-E611-810F-3863BB357C39
//Opportunity: F45D2DF7-6DBF-E511-8109-3863CB343C91
associate: function () {
        bd_Utilities.WebAPI.associateRecords("E48333EE-49B9-E511-810F-3863BB357C38", "accounts", "opportunity_customer_accounts", "F25D2DF7-6CBF-E511-8109-3863BB343C90", "opportunities",
            function () {

            },
            function () {

            });
    }

And the Disassociate

this.disassociateRecords = function (parentId, parentType, relationshipName, childId, childType, successCallback, errorCallback) {
        var req = new XMLHttpRequest();
     
        var webApiPath = getWebAPIPath();
        var parentUri = webApiPath + "/" + parentType + "(" + parentId + ")/";
        var childUri = webApiPath + "/" + childType + "(" + childId + ")";

        req.open("DELETE", encodeURI(parentUri + relationshipName + "/$ref?$id=" + childUri), true);

        req.setRequestHeader("Accept", "application/json");
        req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        req.setRequestHeader("OData-MaxVersion", "4.0");
        req.setRequestHeader("OData-Version", "4.0");
        req.onreadystatechange = function () {
            if (this.readyState == 4 /* complete */) {
                req.onreadystatechange = null;
                if (this.status == 204 || this.status == 1223) {
                    successCallback();
                }
                else {
                    errorCallback(bd_Utilities.WebAPI.errorHandler(this));
                }
            }
        };
        req.send(JSON.stringify());
    };

function getWebAPIPath() {
        return getClientUrl() + "/api/data/v8.0/";
}

function getClientUrl() {
        //Get the organization URL
        if (typeof GetGlobalContext == "function" &&
            typeof GetGlobalContext().getClientUrl == "function") {
            return GetGlobalContext().getClientUrl();
        }
        else {
            //If GetGlobalContext is not defined check for Xrm.Page.context;
            if (typeof Xrm != "undefined" &&
                typeof Xrm.Page != "undefined" &&
                typeof Xrm.Page.context != "undefined" &&
                typeof Xrm.Page.context.getClientUrl == "function") {
                try {
                    return Xrm.Page.context.getClientUrl();
                } catch (e) {
                    throw new Error("Xrm.Page.context.getClientUrl is not available.");
                }
            }
            else { throw new Error("Context is not available."); }
        }
    }

CRM 2016 - WEB API CRUD Operations - Impersonate another User

Web API series Part 1, Part 2, Part 3
Impersonating another user is very simple, you just need to set the XMLHttpRequest header as shown below.
Here are a couple of basic examples on how to impersonate a User in CRUD operations with the new CRM 2016 Web API in Javascript, here I am just going to show you impersonation in Create and Update. Impersonating another user should also be possible in Delete and Retrieve operations. I haven't tried it yet.

updateRecordOnBehalfOf = function (id, object, entitySetName, successCallback, errorCallback, impersonatedUserId) {

        var req = new XMLHttpRequest();
        req.open("PATCH", encodeURI(getWebAPIPath() + entitySetName + "(" + id + ")"), true);
        req.setRequestHeader("MSCRMCallerID", impersonatedUserId);
        req.setRequestHeader("Accept", "application/json");
        req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        req.setRequestHeader("OData-MaxVersion", "4.0");
        req.setRequestHeader("OData-Version", "4.0");
        req.onreadystatechange = function () {
            if (this.readyState == 4 /* complete */) {
                req.onreadystatechange = null;
                if (this.status == 204 || this.status == 1223) {
                    successCallback();
                }
                else {
                    errorCallback(bd_Utilities.WebAPI.errorHandler(this));
                }
            }
        };
        req.send(JSON.stringify(object));
    };

createOnBehalfOf = function (entitySetName, entity, successCallback, errorCallback, impersonatedUserId) {
        var req = new XMLHttpRequest();
        req.open("POST", encodeURI(getWebAPIPath() + entitySetName), true);      
        req.setRequestHeader("MSCRMCallerID", impersonatedUserId);
        req.setRequestHeader("Accept", "application/json");
        req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        req.setRequestHeader("OData-MaxVersion", "4.0");
        req.setRequestHeader("OData-Version", "4.0");
        req.onreadystatechange = function () {
            if (this.readyState == 4 /* complete */) {
                req.onreadystatechange = null;
                if (this.status == 204) {
                    if (successCallback)
                        successCallback(this.getResponseHeader("OData-EntityId"));
                }
                else {
                    if (errorCallback)
                        errorCallback(bd_Utilities.WebAPI.errorHandler(this.response));
                }
            }
        };
        req.send(JSON.stringify(entity));
    };

I hope this help you getting started with the new CRM 2016 Web API.