A Dataverse form script starts at the event handler. Register it with Pass execution context as first parameter , get the form context once, then read the form and call Xrm from there.
var Contoso = window.Contoso || {};
Contoso.Account = Contoso.Account || {};
Contoso.Account. onLoad = function ( executionContext ) {
var formContext = executionContext. getFormContext ();
var globalContext = Xrm.Utility. getGlobalContext ();
var name = formContext. getAttribute ( "name" ). getValue ();
Xrm.Page is deprecated. Always go through executionContext.getFormContext(). The rest of the deprecated calls are listed at the end.
Everything about the event that fired is on executionContext.
Field Code What it tells you Form context executionContext.getFormContext()Entry point to the form or grid the event ran on Event source executionContext.getEventSource()Object that raised the event: the attribute on OnChange, the form on OnLoad, the grid row on grid events Depth executionContext.getDepth()Position of this handler in the chain of handlers for the event Event args executionContext.getEventArgs()Event-specific arguments. Populated for OnSave, OnPostSave, OnLoad, and lookup tag events; null for most others Set shared variable executionContext.setSharedVariable("key", value)Pass a value to later handlers of the same event Get shared variable executionContext.getSharedVariable("key")Read a value an earlier handler stored
Read these from executionContext.getEventArgs() in an OnSave handler.
Field Code What it tells you Save mode eventArgs.getSaveMode()Why the save happened: 1 Save, 2 Save and Close, 59 Save and New, 70 AutoSave, 5 Deactivate, 6 Reactivate, 47 Assign Cancel the save eventArgs.preventDefault()Stops the save. Show a notification so the user knows why Was it cancelled eventArgs.isDefaultPrevented()True when an earlier handler already called preventDefault() Cancel on error eventArgs.preventDefaultOnError()Stops the save only if an error occurs, including an async OnSave handler that rejects
Field Code What it tells you Data load state eventArgs.getDataLoadState()1 initial load, 2 save, 3 refresh
Everything about the current record is on formContext.data.entity.
Field Code What it tells you Id formContext.data.entity.getId()GUID of the record, wrapped in braces. Empty string on Create Entity name formContext.data.entity.getEntityName()Logical name of the table (account, contact, and so on) Entity reference formContext.data.entity.getEntityReference(){ id, entityType, name } for the record, ready to put into a lookupPrimary value formContext.data.entity.getPrimaryAttributeValue()Value of the primary name column Is dirty formContext.data.entity.getIsDirty()True when any column has unsaved changes Is valid formContext.data.entity.isValid()False when a required column is empty or a value is invalid Attributes formContext.data.entity.attributesCollection of every column on the form
Call Code What it does Save formContext.data.save()Save the record. Returns a promise Save and close formContext.data.save({ saveMode: 2 })Save with a specific save mode Refresh formContext.data.refresh(true)Reload data without reloading the form. true saves first. Returns a promise Add OnSave formContext.data.entity.addOnSave(handler)Attach an OnSave handler at runtime Remove OnSave formContext.data.entity.removeOnSave(handler)Detach it Add OnPostSave formContext.data.entity.addOnPostSave(handler)Run code after the save completes Add OnLoad formContext.data.addOnLoad(handler)Run code each time data loads, including after save and refresh
Get a column with formContext.getAttribute("logicalname"). It returns null when the column is not on the form.
Field Code What it tells you Get value attribute.getValue()Current value. Lookups return an array; option sets return the number Set value attribute.setValue(value)Change the value. Does not fire OnChange Fire OnChange attribute.fireOnChange()Run the OnChange handlers after setValue Name attribute.getName()Logical name of the column Type attribute.getAttributeType()string, memo, integer, decimal, money, boolean, datetime, lookup, optionset, multiselectoptionsetIs dirty attribute.getIsDirty()True when this column has unsaved changes Controls attribute.controlsEvery control on the form bound to this column
Field Code What it tells you Required level attribute.setRequiredLevel("required")none, required, or recommended. Read it with getRequiredLevel()Submit mode attribute.setSubmitMode("always")always, never, or dirty. Use always to send a read-only value on saveAdd OnChange attribute.addOnChange(handler)Attach an OnChange handler at runtime Remove OnChange attribute.removeOnChange(handler)Detach it
Type Code What it tells you Lookup attribute.setValue([{ id: guid, name: "Contoso", entityType: "account" }])Always an array of objects, even for a single-value lookup Clear lookup attribute.setValue(null)Removes the value Option set attribute.getText()Label of the selected option. getValue() returns the number Option list attribute.getOptions()Every { value, text } defined for the column Selected option attribute.getSelectedOption(){ value, text } of the current choiceDate attribute.setValue(new Date())Pass a JavaScript Date Two options attribute.setValue(true)Pass a boolean
Get a control with formContext.getControl("logicalname"). A column on the form twice has a second control named logicalname1.
Field Code What it tells you Show or hide control.setVisible(false)Read it with getVisible() Lock or unlock control.setDisabled(true)Read it with getDisabled() Label control.setLabel("New label")Change the label shown on the form Focus control.setFocus()Move the cursor to the control Attribute control.getAttribute()Column the control is bound to Control type control.getControlType()standard, lookup, optionset, subgrid, webresource, iframe, and so on
Field Code What it tells you Field error control.setNotification("Message", "uniqueId")Red error on the field. Blocks save until cleared Clear it control.clearNotification("uniqueId")Remove that notification Recommendation control.addNotification({ messages: ["Message"], notificationLevel: "RECOMMENDATION", uniqueId: "id", actions: [...] })Light-bulb hint with optional actions. Use ERROR for a blocking error
Field Code What it tells you Before search control.addPreSearch(handler)Runs before the lookup shows results. Add filters here Filter results control.addCustomFilter(fetchXmlFilter, "account")Add a <filter> block. Call it only inside a PreSearch handler Remove PreSearch control.removePreSearch(handler)Detach the handler Custom view control.addCustomView(viewId, entityName, viewDisplayName, fetchXml, layoutXml, isDefault)Add a view built from FetchXML to the lookup
Field Code What it tells you Remove option control.removeOption(value)Hide one choice from the dropdown Add option control.addOption({ value: 1, text: "Label" }, index)Add a choice back. It must exist in the column definition Clear options control.clearOptions()Remove every choice from the dropdown
Field Code What it tells you Refresh control.refresh()Reload the subgrid rows Grid control.getGrid()Access rows through getRows() and getSelectedRows() Row count control.getGrid().getTotalRecordCount()Number of records in the subgrid On load control.addOnLoad(handler)Runs every time the subgrid loads or refreshes
Field Code What it tells you Form type formContext.ui.getFormType()0 Undefined, 1 Create, 2 Update, 3 Read Only, 4 Disabled, 6 Bulk Edit Current form formContext.ui.formSelector.getCurrentItem()Current main form. Use getId() and getLabel() on it Switch form formContext.ui.formSelector.items.get(formId).navigate()Open another main form for the same record Close formContext.ui.close()Close the form Refresh ribbon formContext.ui.refreshRibbon()Re-evaluate command bar enable and display rules
Field Code What it tells you Show formContext.ui.setFormNotification("Message", "WARNING", "uniqueId")Banner at the top of the form. Level is ERROR, WARNING, or INFO Clear formContext.ui.clearFormNotification("uniqueId")Remove that banner
Field Code What it tells you Tab formContext.ui.tabs.get("tabName")Tab by the name set in the form designer Show or hide tab tab.setVisible(false)Hides the tab and everything in it Expand or collapse tab.setDisplayState("collapsed")expanded or collapsedFocus tab tab.setFocus()Select the tab Section tab.sections.get("sectionName")Section inside that tab Show or hide section section.setVisible(false)Hides the section and its controls Tab change tab.addTabStateChange(handler)Runs when the tab expands or collapses
Every call returns a promise. Use Xrm.WebApi for online and offline; use Xrm.WebApi.online for execute.
Call Code What it does Create Xrm.WebApi.createRecord("account", data)Insert a record. Resolves to { entityType, id } Retrieve Xrm.WebApi.retrieveRecord("account", id, "?$select=name,revenue")Read one record. Always use $select RetrieveMultiple Xrm.WebApi.retrieveMultipleRecords("account", "?$select=name&$filter=statecode eq 0", 50)Query with OData. Resolves to { entities, nextLink } FetchXML Xrm.WebApi.retrieveMultipleRecords("account", "?fetchXml=" + encodeURIComponent(fetchXml))Query with FetchXML Update Xrm.WebApi.updateRecord("account", id, data)Write only the properties in data Delete Xrm.WebApi.deleteRecord("account", id)Remove a record Execute Xrm.WebApi.online.execute(request)Send an action, function, or custom API request Execute batch Xrm.WebApi.online.executeMultiple(requests)Send several requests together. Nest an array for a change set
Use Code What it tells you Set a lookup "parentcustomerid_account@odata.bind": "/accounts(" + id + ")"Navigation property name plus the entity set name Clear a lookup Xrm.WebApi.updateRecord("contact", id, { "parentcustomerid_account": null })Use the single-valued navigation property name Read a lookup result["_parentcustomerid_value"]GUID of the related record Lookup label result["_parentcustomerid_value@OData.Community.Display.V1.FormattedValue"]Display name of the related record Option label result["industrycode@OData.Community.Display.V1.FormattedValue"]Label for an option set value Strip braces id.replace(/[{}]/g, "")getId() returns braces; the Web API does not want them
execute needs a request object with getMetadata.
Target: { entityType: "account" , id: accountId },
getMetadata : function () {
boundParameter: "entity" ,
Target: { typeName: "mscrm.account" , structuralProperty: 5 }
operationType: 0 , // 0 action, 1 function, 2 CRUD
operationName: "contoso_RecalculateCredit"
Xrm.WebApi.online. execute (request)
. then ( function ( response ) { return response. json (); })
. then ( function ( result ) { console. log (result); });
Use boundParameter: null and drop Target for an unbound custom API.
Call Code What it does Alert Xrm.Navigation.openAlertDialog({ title: "Title", text: "Message" })One-button dialog. Resolves when closed Confirm Xrm.Navigation.openConfirmDialog({ title: "Title", text: "Continue?" })Resolves to { confirmed: true/false } Error Xrm.Navigation.openErrorDialog({ message: "Message", details: "Stack" })Error dialog with a downloadable details file
Call Code What it does Open form Xrm.Navigation.openForm({ entityName: "account", entityId: id })Open a record. Drop entityId to open a new one Quick create Xrm.Navigation.openForm({ entityName: "contact", useQuickCreateForm: true }, defaults)Open quick create with default values Navigate Xrm.Navigation.navigateTo({ pageType: "entityrecord", entityName: "account", entityId: id }, { target: 2, position: 1, width: { value: 50, unit: "%" } })target: 2 opens a modal dialog; position: 2 makes it a side dialogOpen list Xrm.Navigation.navigateTo({ pageType: "entitylist", entityName: "account" })Go to a table’s grid view Custom page Xrm.Navigation.navigateTo({ pageType: "custom", name: "contoso_mypage_12345" }, { target: 2 })Open a canvas custom page Web resource Xrm.Navigation.navigateTo({ pageType: "webresource", webresourceName: "contoso_/page.html", data: "id=1" }, { target: 2 })Open an HTML web resource in a dialog URL Xrm.Navigation.openUrl("https://contoso.com")Open an external URL in a new window
Call Code What it does Global context Xrm.Utility.getGlobalContext()User, organization, and client information Show spinner Xrm.Utility.showProgressIndicator("Working...")Blocking progress indicator Hide spinner Xrm.Utility.closeProgressIndicator()Close it. Call it in both success and error paths Lookup dialog Xrm.Utility.lookupObjects({ entityTypes: ["account"], allowMultiSelect: false })Resolves to the selected { id, name, entityType } array Metadata Xrm.Utility.getEntityMetadata("account", ["industrycode"])Table and column metadata, including option set labels Localized string Xrm.Utility.getResourceString("contoso_/strings", "key")Read a value from a RESX web resource Page context Xrm.Utility.getPageContext()Current page input, such as entity name and id Status transitions Xrm.Utility.getAllowedStatusTransitions("incident", stateCode)Status reasons allowed from the given state
Read these from Xrm.Utility.getGlobalContext().
Field Code What it tells you UserId globalContext.userSettings.userIdGUID of the signed-in user UserName globalContext.userSettings.userNameDisplay name of the signed-in user Roles globalContext.userSettings.rolesCollection of { id, name } security roles. Use forEach or get LanguageId globalContext.userSettings.languageIdLCID of the user’s UI language (1033 English) Time zone globalContext.userSettings.getTimeZoneOffsetMinutes()User’s offset from UTC in minutes
Field Code What it tells you Client URL globalContext.getClientUrl()Base URL of the environment. Use it to build Web API URLs Unique name globalContext.organizationSettings.uniqueNameUnique name of the environment Organization id globalContext.organizationSettings.organizationIdGUID of the organization Base currency globalContext.organizationSettings.baseCurrency{ id, name, entityType } of the base currencyVersion globalContext.getVersion()Dataverse version number Current app globalContext.getCurrentAppProperties()Promise resolving to the model-driven app’s appId, displayName, and uniqueName
Field Code What it tells you Client globalContext.client.getClient()Web, Outlook, or MobileForm factor globalContext.client.getFormFactor()0 Unknown, 1 Desktop, 2 Tablet, 3 Phone Offline globalContext.client.isOffline()True when running offline in the mobile app
Call Code What it does Global banner Xrm.App.addGlobalNotification({ type: 2, level: 3, message: "Message", showCloseButton: true })App-level banner. Level 1 success, 2 error, 3 warning, 4 info. Resolves to an id Clear banner Xrm.App.clearGlobalNotification(id)Remove that banner Side pane Xrm.App.sidePanes.createPane({ title: "Details", paneId: "details", canClose: true })Add a side pane. Call navigate(pageInput) on it to load content
Pass PrimaryControl as a CRM parameter on the command. On a form it is the form context; on a grid it is the grid context.
Use Code What it tells you Form command function run(primaryControl) { var formContext = primaryControl; }Same object as executionContext.getFormContext() Selected ids Pass SelectedControlSelectedItemIds Array of GUIDs of the selected grid rows Enable rule function isEnabled(primaryControl) { return true; }Return a boolean or a promise that resolves to one Re-evaluate formContext.ui.refreshRibbon()Run enable and display rules again after a value changes
These calls still run. Microsoft has not removed them, and Xrm.Page will stay longer than the others because so many scripts still use it. New scripts should call the replacement.
Deprecated Use instead What changed Xrm.PageexecutionContext.getFormContext()On a command, pass PrimaryControl. parent.Xrm.Page still works from an HTML web resource embedded on a form Xrm.Page.contextXrm.Utility.getGlobalContext()Global context no longer hangs off the form Xrm.Page.context.getQueryStringParameters()formContext.data.attributesQuery-string values and openForm parameters arrive as attributes formContext.data.entity.save()formContext.data.save()Save moved onto formContext.data Xrm.Page.data.entity.getDataXml()Same method On a lookup, read typename, not type
globalContext is Xrm.Utility.getGlobalContext().
Deprecated Use instead What changed getTimeZoneOffsetMinutes()globalContext.userSettings.getTimeZoneOffsetMinutes()Moved to user settings getUserId()globalContext.userSettings.userIdMoved to user settings getUserLcid()globalContext.userSettings.languageIdMoved to user settings getUserName()globalContext.userSettings.userNameMoved to user settings getUserRoles()globalContext.userSettings.rolessecurityRoles was the first replacement, and it is deprecated toogetIsAutoSaveEnabled()globalContext.organizationSettings.isAutoSaveEnabledMoved to organization settings getOrgLcid()globalContext.organizationSettings.languageIdMoved to organization settings getOrgUniqueName()globalContext.organizationSettings.uniqueNameMoved to organization settings userSettings.securityRolesuserSettings.rolesroles includes the display name, not only the GUIDuserSettings.transactionCurrencyIduserSettings.transactionCurrencyReturns { id, name, entityType } organizationSettings.baseCurrencyIdorganizationSettings.baseCurrencyReturns { id, name, entityType }
Deprecated Use instead What changed Xrm.Utility.alertDialogXrm.Navigation.openAlertDialogReturns a promise, same shape as the other navigation calls Xrm.Utility.confirmDialogXrm.Navigation.openConfirmDialogResolves to { confirmed } Xrm.Utility.openEntityFormXrm.Navigation.openFormNavigation lives on Xrm.Navigation Xrm.Utility.openQuickCreateXrm.Navigation.openFormPass useQuickCreateForm: true Xrm.Utility.openWebResourceXrm.Navigation.openWebResourceOn Unified Interface this returns nothing Xrm.Utility.getBarcodeValueXrm.Device.getBarcodeValueDevice calls live on Xrm.Device Xrm.Utility.getCurrentPositionXrm.Device.getCurrentPositionDevice calls live on Xrm.Device Xrm.Utility.isActivityTypeXrm.Utility.getEntityMetadataThe replacement is async, so it cannot run inside a ribbon rule Xrm.Mobile.offlineXrm.WebApi.offlineOffline calls live on Xrm.WebApi
Deprecated Use instead What changed addOnKeyPressA Power Apps component framework control No client-API replacement fireOnKeyPressA Power Apps component framework control No client-API replacement removeOnKeyPressA Power Apps component framework control No client-API replacement showAutoCompleteA Power Apps component framework control No client-API replacement hideAutoCompleteA Power Apps component framework control No client-API replacement GridRow.getData()GridRow.dataSame shape as formContext.data GridRowData.getEntity()GridRowData.entitySame shape as formContext.data.entity getObject()getContentWindow()On an HTML web resource control parent.Xrmcontrol.getContentWindow()parent.Xrm only works while the web resource is inside a form. A new window uses opener.Xrm
Deprecated Use instead What changed getData and setData on a Silverlight web resourceNone Silverlight is unsupported. These methods were removed after October 2020
Source: Some client APIs are deprecated .
Leave secrets and API keys out of web resources. Anything in client script is readable by the user.