Ways to Call Web API in Dynamics CRM with JavaScript

Below are the various methods to call the Dynamics 365 Web API from JavaScript on an Account form. Each method is demonstrated with a code example, such as retrieving an Account record or updating a Contact. These examples assume they are executed within a form event (e.g., OnLoad, OnChange) and use the executionContext.

1. Using Xrm.WebApi (Client API)

The Xrm.WebApi object provides a promise-based interface for CRUD operations. It’s the recommended method for simple Web API calls in Dynamics 365.

function retrieveAccountUsingXrmWebApi(executionContext) {
    var formContext = executionContext.getFormContext();
    var accountId = formContext.data.entity.getId().replace("{", "").replace("}", "");
    
    // Retrieve Account record
    Xrm.WebApi.retrieveRecord("account", accountId, "?$select=name,revenue").then(
        function(result) {
            console.log("Account Name: " + result.name);
            console.log("Revenue: " + result.revenue);
            formContext.ui.setFormNotification(
                "Account retrieved: " + result.name,
                "INFO",
                "retrieveSuccess"
            );
        },
        function(error) {
            console.log("Error: " + error.message);
            formContext.ui.setFormNotification(
                "Error retrieving account: " + error.message,
                "ERROR",
                "retrieveError"
            );
        }
    );
}

2. Using fetch API

The modern fetch API is a browser-standard method for making HTTP requests. It requires manual header setup for authentication in Dynamics 365.

function retrieveAccountUsingFetch(executionContext) {
    var formContext = executionContext.getFormContext();
    var accountId = formContext.data.entity.getId().replace("{", "").replace("}", "");
    var url = Xrm.Utility.getGlobalContext().getClientUrl() + 
              "/api/data/v9.2/accounts(" + accountId + ")?$select=name,revenue";
    
    fetch(url, {
        method: "GET",
        headers: {
            "OData-MaxVersion": "4.0",
            "OData-Version": "4.0",
            "Accept": "application/json",
            "Content-Type": "application/json; charset=utf-8",
            "Authorization": "Bearer " + Xrm.Utility.getGlobalContext().getAuthenticationHeader() // Optional, typically handled by browser in CRM context
        }
    })
    .then(response => {
        if (!response.ok) throw new Error("HTTP error: " + response.status);
        return response.json();
    })
    .then(data => {
        console.log("Account Name: " + data.name);
        console.log("Revenue: " + data.revenue);
        formContext.ui.setFormNotification(
            "Account retrieved: " + data.name,
            "INFO",
            "fetchSuccess"
        );
    })
    .catch(error => {
        console.log("Error: " + error.message);
        formContext.ui.setFormNotification(
            "Error retrieving account: " + error.message,
            "ERROR",
            "fetchError"
        );
    });
}

3. Using XMLHttpRequest (XHR)

The classic XMLHttpRequest object provides fine-grained control over HTTP requests. It’s widely supported and useful for complex scenarios like batch requests.

function retrieveAccountUsingXHR(executionContext) {
    var formContext = executionContext.getFormContext();
    var accountId = formContext.data.entity.getId().replace("{", "").replace("}", "");
    var url = Xrm.Utility.getGlobalContext().getClientUrl() + 
              "/api/data/v9.2/accounts(" + accountId + ")?$select=name,revenue";
    
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.setRequestHeader("OData-MaxVersion", "4.0");
    xhr.setRequestHeader("OData-Version", "4.0");
    xhr.setRequestHeader("Accept", "application/json");
    xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                var data = JSON.parse(xhr.responseText);
                console.log("Account Name: " + data.name);
                console.log("Revenue: " + data.revenue);
                formContext.ui.setFormNotification(
                    "Account retrieved: " + data.name,
                    "INFO",
                    "xhrSuccess"
                );
            } else {
                console.log("Error: " + xhr.statusText);
                formContext.ui.setFormNotification(
                    "Error retrieving account: " + xhr.statusText,
                    "ERROR",
                    "xhrError"
                );
            }
        }
    };
    
    xhr.send();
}

4. Using jQuery.ajax

If jQuery is included as a web resource in Dynamics 365, jQuery.ajax provides a convenient way to make Web API calls with simplified syntax.

function retrieveAccountUsingJQuery(executionContext) {
    var formContext = executionContext.getFormContext();
    var accountId = formContext.data.entity.getId().replace("{", "").replace("}", "");
    var url = Xrm.Utility.getGlobalContext().getClientUrl() + 
              "/api/data/v9.2/accounts(" + accountId + ")?$select=name,revenue";
    
    $.ajax({
        url: url,
        type: "GET",
        headers: {
            "OData-MaxVersion": "4.0",
            "OData-Version": "4.0",
            "Accept": "application/json",
            "Content-Type": "application/json; charset=utf-8"
        },
        success: function(data) {
            console.log("Account Name: " + data.name);
            console.log("Revenue: " + data.revenue);
            formContext.ui.setFormNotification(
                "Account retrieved: " + data.name,
                "INFO",
                "jquerySuccess"
            );
        },
        error: function(xhr, status, error) {
            console.log("Error: " + error);
            formContext.ui.setFormNotification(
                "Error retrieving account: " + error,
                "ERROR",
                "jqueryError"
            );
        }
    });
}

5. Using Xrm.WebApi.online.execute (Custom Actions)

The Xrm.WebApi.online.execute method is used to call custom actions or workflows defined in Dynamics 365.

function executeCustomAction(executionContext) {
    var formContext = executionContext.getFormContext();
    var accountId = formContext.data.entity.getId().replace("{", "").replace("}", "");
    
    // Example custom action: "new_CustomAction" (replace with your action name)
    var request = {
        entity: { entityType: "account", id: accountId },
        getMetadata: function() {
            return {
                boundParameter: "entity",
                parameterTypes: {
                    "entity": { "typeName": "mscrm.account", "structuralProperty": 5 }
                },
                operationType: 0, // 0 = Action
                operationName: "new_CustomAction"
            };
        }
    };
    
    Xrm.WebApi.online.execute(request).then(
        function(response) {
            return response.json().then(function(data) {
                console.log("Custom Action Result: " + JSON.stringify(data));
                formContext.ui.setFormNotification(
                    "Custom action executed successfully.",
                    "INFO",
                    "actionSuccess"
                );
            });
        },
        function(error) {
            console.log("Error: " + error.message);
            formContext.ui.setFormNotification(
                "Error executing action: " + error.message,
                "ERROR",
                "actionError"
            );
        }
    );
}

6. Using Xrm.WebApi.online.executeMultiple (Batch Operations)

The Xrm.WebApi.online.executeMultiple method allows executing multiple requests in a single call, though it’s limited to non-batch CRUD operations.

function updateMultipleContacts(executionContext) {
    var formContext = executionContext.getFormContext();
    var accountId = formContext.data.entity.getId().replace("{", "").replace("}", "");
    
    // Retrieve related Contacts first
    Xrm.WebApi.retrieveMultipleRecords("contact", "?$select=contactid&$filter=_parentcustomerid_value eq " + accountId).then(
        function(result) {
            var requests = result.entities.map(function(contact) {
                return {
                    getMetadata: function() {
                        return {
                            boundParameter: null,
                            operationType: 2, // 2 = Update
                            operationName: "Update"
                        };
                    },
                    entity: {
                        entityType: "contact",
                        id: contact.contactid,
                        "donotemail": true // Update field
                    }
                };
            });
            
            // Execute multiple updates
            Xrm.WebApi.online.executeMultiple(requests).then(
                function(results) {
                    console.log("Updated " + results.length + " contacts.");
                    formContext.ui.setFormNotification(
                        "Updated " + results.length + " contacts.",
                        "INFO",
                        "batchSuccess"
                    );
                },
                function(error) {
                    console.log("Error: " + error.message);
                    formContext.ui.setFormNotification(
                        "Error updating contacts: " + error.message,
                        "ERROR",
                        "batchError"
                    );
                }
            );
        }
    );
}

Notes

  • Xrm.WebApi: Simplest and recommended for standard CRUD operations. Limited to single-entity operations unless using executeMultiple.
  • fetch: Modern, flexible, but requires manual header management. Ideal for external APIs or when avoiding legacy methods.
  • XMLHttpRequest: Offers maximum control, especially for batch requests (e.g., $batch). More verbose but widely supported.
  • jQuery.ajax: Requires jQuery as a web resource. Convenient but adds dependency overhead.
  • Xrm.WebApi.online.execute: Specific to custom actions/workflows. Requires action definition in Dynamics 365.
  • Xrm.WebApi.online.executeMultiple: Useful for multiple operations, but doesn’t support true batching like $batch with XHR.
  • Authentication: Within Dynamics 365, authentication is typically handled by the browser session, so no explicit tokens are needed.
  • Testing: Use browser developer tools (F12) to debug with console.log.

These methods cover the primary ways to interact with the Dynamics 365 Web API via JavaScript. Choose based on your scenario: Xrm.WebApi for simplicity, fetch or XHR for flexibility, and jQuery if already in use. 

Explanation of Each Method:

  1. Xrm.WebApi:
    • Use Case: Standard CRUD operations (create, retrieve, update, delete).
    • Pros: Built-in, promise-based, no manual header setup.
    • Cons: Limited to single-entity operations unless using executeMultiple.
  2. fetch API:
    • Use Case: Modern HTTP requests, including external APIs.
    • Pros: Clean syntax, native to modern browsers, supports promises.
    • Cons: Requires manual header configuration.
  3. XMLHttpRequest (XHR):
    • Use Case: Complex scenarios like batch requests ($batch).
    • Pros: Full control over request/response, widely supported.
    • Cons: Verbose, callback-based (unless wrapped in promises).
  4. jQuery.ajax:
    • Use Case: Simplified AJAX calls if jQuery is available.
    • Pros: Easy syntax, handles cross-browser compatibility.
    • Cons: Requires jQuery as a dependency, less common in modern Dynamics 365 projects.
  5. Xrm.WebApi.online.execute:
    • Use Case: Calling custom actions or workflows.
    • Pros: Integrates with Dynamics 365 custom logic.
    • Cons: Requires predefined actions/workflows.
  6. Xrm.WebApi.online.executeMultiple:
    • Use Case: Multiple operations in one call (e.g., bulk updates).
    • Pros: Reduces round-trips for multiple requests.
    • Cons: Not a true batch (no $batch support), limited to 1000 operations.

Additional Considerations:

  • Batch Requests: For true batching (e.g., combining multiple CRUD operations in one request), use XMLHttpRequest with the $batch endpoint, as shown in the previous "Batch Record Updates" example.
  • External APIs: fetch or XMLHttpRequest are better suited for external services, requiring CORS or proxy setup.
  • Error Handling: All methods benefit from robust error handling (e.g., notifications, logging).

Leave a Comment