IHonest Blog

Ways to Call Web API in Dynamics CRM with JavaScript

Written by Rifaqat Jumani | Apr 8, 2025 11:56:24 PM

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).