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".datais 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);
}
);
}
optionsaccepts 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
.entitiesarray and may include.nextLinkfor 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.
updateRecorduses 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.WebApimethods return Promises; usingawaitmakes 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
XMLHttpRequestwithopen(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/awaitwithXrm.WebApi. softchief.com
10 — Additional useful tips & best practices
- Always handle rejections (
.catchor try/catch aroundawait). - Minimize fields returned with
$selectto reduce payload. - Use
retrieveMultipleRecordspaging when many records returned; checknextLink. - Use
updateRecordPATCH semantics — send only changed attributes. Microsoft Learn - For batch or multi-request scenarios, consider
executeMultipleon 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.updateRecordand related methods. Microsoft Learn Xrm.WebApi.online.executedocs for executing actions/functions. Microsoft Learn- Community posts showing
async/awaitpatterns for sequencingXrm.WebApicalls. Microsoft Dynamics Community+1 - Articles showing synchronous XHR approach (for completeness — use cautiously).

Leave a comment