1 — Quick overview

Xrm.WebApi (v9) exposes client-side methods that return Promises (so they are asynchronous). Main methods you’ll use:

  • Xrm.WebApi.createRecord(entityLogicalName, data)
  • Xrm.WebApi.retrieveRecord(entityLogicalName, id, options)
  • Xrm.WebApi.retrieveMultipleRecords(entityLogicalName, options)
  • Xrm.WebApi.updateRecord(entityLogicalName, id, data)
  • Xrm.WebApi.deleteRecord(entityLogicalName, id)
  • Xrm.WebApi.online.execute(request) — execute actions/functions or more advanced requests.

2 — Create (insert) a record





// Create an account
function createAccount() {
  const account = {
    name: "Contoso Ltd",
    telephone1: "123-456-7890",
    description: "Created via Xrm.WebApi.createRecord"
  };

  Xrm.WebApi.createRecord("account", account).then(
    function (result) {
      // result.id is the GUID of the new record
      console.log("Account created. Id:", result.id);
    },
    function (error) {
      console.error("Create failed:", error.message);
    }
  );
}

Notes:

  • entityLogicalName = logical name like "account", "contact".
  • data is a plain JS object with schema names. (Use lookup navigation properties or odata-formats for related entities.)

3 — Retrieve a single record

// Retrieve account by id and select specific fields
function getAccount(accountId) {
  Xrm.WebApi.retrieveRecord("account", accountId, "?$select=name,emailaddress1").then(
    function (result) {
      console.log("Account name:", result.name);
      console.log("Email:", result.emailaddress1);
    },
    function (error) {
      console.error("Retrieve failed:", error.message);
    }
  );
}

  • options accepts OData query options like $select, $expand, $filter (for retrieveMultiple). Microsoft Learn

4 — Retrieve multiple records

// Retrieve multiple accounts
function getAccounts() {
  Xrm.WebApi.retrieveMultipleRecords("account", "?$select=name,revenue&$top=50").then(
    function (result) {
      result.entities.forEach(e => console.log(e.name, e.revenue));
      // handle paging: result._nextLink if present
      if (result.nextLink) {
        // call Xrm.WebApi.retrieveMultipleRecords with nextLink to get more
      }
    },
    function (error) {
      console.error("retrieveMultiple failed:", error.message);
    }
  );
}

  • Result contains .entities array and may include .nextLink for paging. Microsoft Learn

5 — Update a record

// Update account's telephone
function updateAccount(accountId) {
  const data = { telephone1: "555-555-5555" };

  Xrm.WebApi.updateRecord("account", accountId, data).then(
    function (result) {
      console.log("Update successful", result); // may include id & entityType
    },
    function (error) {
      console.error("Update failed:", error.message);
    }
  );
}

  • Only send the fields that change. updateRecord uses PATCH semantics. Microsoft Learn

6 — Delete a record

function deleteAccount(accountId) {
  Xrm.WebApi.deleteRecord("account", accountId).then(
    function () {
      console.log("Delete successful");
    },
    function (error) {
      console.error("Delete failed:", error.message);
    }
  );
}


7 — Execute actions / functions / custom requests

Use Xrm.WebApi.online.execute for actions or advanced requests:

const request = {
  // Example format for an action or function request object
  // See MS docs for correct shape for specific actions/functions
};

Xrm.WebApi.online.execute(request).then(function(response) {
  if (response.ok) {
    // parse response.json() as needed
  }
}, function(error){
  console.error(error);
});

Use execute when you need to call custom actions, bound actions/functions, or use batch/complex requests. Microsoft Learn


8 — Better patterns: Promises, async/await, sequencing & parallel calls

Use async / await to write linear-looking code (recommended)

Because Xrm.WebApi returns Promises, you can use async/await to sequence calls so code reads and behaves like synchronous code:

async function createAndThenRetrieve() {
  try {
    const createResult = await Xrm.WebApi.createRecord("account", { name: "Acme" });
    const id = createResult.id;
    const record = await Xrm.WebApi.retrieveRecord("account", id, "?$select=name");
    console.log("Created & retrieved:", record.name);
  } catch (err) {
    console.error("Error:", err.message);
  }
}

  • This does not block the UI thread — it just lets you write sequential code by waiting for promises. Use this pattern for predictable ordering. Microsoft Dynamics Community+1

Parallel calls with Promise.all

If two independent requests can run concurrently:

async function parallelExample() {
  const p1 = Xrm.WebApi.retrieveRecord("account", id1, "?$select=name");
  const p2 = Xrm.WebApi.retrieveRecord("contact", id2, "?$select=fullname");
  const [acc, contact] = await Promise.all([p1, p2]);
  // use acc and contact
}


9 — “Synchronous” calls — what’s possible and what’s not

Preferred approach (recommended): use async / await to sequence code

  • Xrm.WebApi methods return Promises; using await makes your code wait for results before continuing — this is the modern, supported way to create synchronous-looking flows without blocking the browser. It’s supported in modern Dynamics Client scripts. (Example above.) Microsoft Dynamics Community+1

True synchronous/blocking XHR — not recommended and often problematic

  • You can make a synchronous HTTP call using XMLHttpRequest with open(url, false) (i.e., async=false), but this will block the UI thread (freeze the browser), can break the Unified Interface/modern clients, and some browsers or environments may disallow it or produce warnings. Use only if you absolutely must and you understand the UX consequences. Microsoft and community blogs show patterns, but advise caution. softchief.com+1

Example (synchronous XHR) — do not use in normal UCI/onLoad scenarios:

function syncWebApiCall(path) {
  var req = new XMLHttpRequest();
  req.open("GET", Xrm.Utility.getGlobalContext().getClientUrl() + path, false); // false => synchronous
  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.send(null);
  if (req.status === 200) {
    return JSON.parse(req.responseText);
  } else {
    throw new Error("Sync request failed: " + req.statusText);
  }
}

  • Again — strongly discouraged. Prefer async/await with Xrm.WebApi. softchief.com

10 — Additional useful tips & best practices

  • Always handle rejections (.catch or try/catch around await).
  • Minimize fields returned with $select to reduce payload.
  • Use retrieveMultipleRecords paging when many records returned; check nextLink.
  • Use updateRecord PATCH semantics — send only changed attributes. Microsoft Learn
  • For batch or multi-request scenarios, consider executeMultiple on server or batch requests where appropriate.
  • Security: requests are executed under the current user’s privileges. Ensure correct permissions and request shapes for actions/functions.
  • Form event handlers: If you use async functions as event handlers, ensure Dynamics supports them in your client version — returning a Promise from handlers is increasingly supported but test in your target environment. Microsoft Dynamics Community+1

11 — Troubleshooting / common errors

  • 400 / 404 — wrong entity name or wrong GUID format; GUID must be in {}-less form.
  • 403 — insufficient privileges.
  • CORS / mixed content — if calling external endpoints, the browser will enforce CORS. For Dataverse/Dynamics endpoints called from form scripts this is usually not an issue.
  • UI freezes when using synchronous XHR — avoid synchronous calls to prevent poor UX. softchief.com

12 — Useful references (recommended reading)

  • Microsoft Client API docs: Xrm.WebApi.updateRecord and related methods. Microsoft Learn
  • Xrm.WebApi.online.execute docs for executing actions/functions. Microsoft Learn
  • Community posts showing async/await patterns for sequencing Xrm.WebApi calls. Microsoft Dynamics Community+1
  • Articles showing synchronous XHR approach (for completeness — use cautiously).

Leave a comment

Copyright © 2025 Dynamics Services Group