Xrm WebApi vs XMLHttpRequest in Dynamics 365

JavaScript in Dynamics 365 – Xrm.WebApi, XMLHttpRequest & Practical Code Examples
📘 Dynamics 365 Development

JavaScript in Dynamics 365 – Xrm.WebApi, XMLHttpRequest & Practical Code Examples

A step-by-step guide for beginners and professionals on the modern way to write JavaScript in D365 — covering Xrm.WebApi, deprecated XMLHttpRequest, form utilities, and real-world code examples.

🗓️ 2026 👤 D365 Certified Developer ⏱️ 10 min read 💡 Beginner + Professional

Introduction

If you are working with Dynamics 365 or Power Apps Model-Driven Apps, JavaScript is one of the most important skills you need. It allows you to add custom logic, fetch data, update records, and control form behavior — all without writing server-side code.

In this blog, we will cover everything step by step:

  • What is Xrm.WebApi and why it is the right choice today
  • ⚠️What is XMLHttpRequest and why Microsoft is deprecating it
  • 🔧Other important JavaScript utilities every D365 developer must know
  • 📋Real code examples — get multiple records, get first record, read lookup and option set fields

Whether you are just starting with D365 development or already have experience, this guide will help you write better, cleaner, and future-proof JavaScript.


What is JavaScript in Dynamics 365?

In Dynamics 365, JavaScript is written inside Web Resources. These are .js files that you upload to your solution and attach to form events — such as form load, field change, or record save.

JavaScript in D365 allows you to:

  • 📥Read and write field values on a form
  • 🔍Fetch records from Dataverse using Web API
  • 📝Create, update, or delete records
  • 🔔Show messages, alerts, and confirmation dialogs
  • 🔗Navigate between records and forms

Microsoft provides a built-in global object called Xrm which gives you access to everything — form context, WebApi, navigation, and utilities. This is your starting point for all JavaScript development in D365.


⚡ Xrm.WebApi – The Modern Standard

What is Xrm.WebApi?

Xrm.WebApi is the official Microsoft-recommended JavaScript API for interacting with Dataverse data. It was introduced to replace the old XMLHttpRequest approach and is now the standard for all D365 JavaScript development.

✅ Officially supported by Microsoft ✅ Promise-based and async ✅ Clean and readable syntax ✅ No extra setup needed

Supported Operations

OperationMethodWhen to Use
Get a single record by IDXrm.WebApi.retrieveRecordWhen you already have the record GUID
Get multiple recordsXrm.WebApi.retrieveMultipleRecordsWhen you need a list with filters
Create a new recordXrm.WebApi.createRecordInsert new data into Dataverse
Update an existing recordXrm.WebApi.updateRecordModify fields of an existing record
Delete a recordXrm.WebApi.deleteRecordRemove a record from Dataverse

⚠️ XMLHttpRequest – Now Going Deprecated

What is XMLHttpRequest?

XMLHttpRequest (also called XHR) was the old way of making HTTP calls in Dynamics 365 JavaScript. Before Xrm.WebApi existed, developers used XHR to call the Web API directly and fetch or post data.

Many older D365 projects and legacy customizations still use it. However, Microsoft has officially deprecated synchronous XMLHttpRequest in form scripts, and modern browsers are also restricting its use.

⚠️ Deprecation Notice: Microsoft's official documentation now flags synchronous XMLHttpRequest as deprecated. Using it can cause form freezes, browser errors, and unexpected behavior in modern environments.

What Did the Old Code Look Like?

JavaScript ❌ OLD WAY – Do NOT use this in new development
// ❌ OLD WAY – Do NOT use this in new development
var req = new XMLHttpRequest();
req.open(
    "GET",
    Xrm.Page.context.getClientUrl() +
    "/api/data/v9.2/accounts?$select=name,telephone1",
    false  // false = synchronous – this is the problem
);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version",    "4.0");
req.setRequestHeader("Accept",           "application/json");
req.send();

var result = JSON.parse(req.responseText);
console.log(result.value[0].name);

Why is it Deprecated?

ProblemExplanation
🚫 Synchronous executionThe form completely freezes while waiting for the API response
🚫 Poor user experienceUsers cannot interact with the form during the call
🚫 Browser restrictionsChrome, Edge, and Firefox are actively blocking synchronous XHR
🚫 Microsoft warningOfficial Microsoft docs now flag this as deprecated behavior
✅ Use insteadXrm.WebApi — async, promise-based, and fully supported
💡 Developer Note: If you find XMLHttpRequest in any existing customization, plan to refactor it. It may still work today in some environments, but it is not safe for long-term use and can cause issues in browser updates.

🔧 Other Important JavaScript Utilities in D365

Before jumping into code examples, let us understand the other commonly used objects that every D365 JavaScript developer uses on a daily basis.

1. formContext – Working with Form Fields

formContext is how you read and write values on a Dynamics 365 form. It is always passed through the executionContext parameter in your function.

⚠️ Important: Always use executionContext.getFormContext() to get the form context. The old Xrm.Page approach is also deprecated and should not be used in any new development.
JavaScript formContext – Read, Write & Control Fields
function onFormLoad(executionContext) {

    // Always get formContext from executionContext – never use Xrm.Page
    var formContext = executionContext.getFormContext();

    // ✅ Read a field value
    var accountName = formContext.getAttribute("name").getValue();
    console.log("Account Name: " + accountName);

    // ✅ Set a field value
    formContext.getAttribute("telephone1").setValue("9999999999");

    // ✅ Make a field required
    formContext.getAttribute("emailaddress1").setRequiredLevel("required");

    // ✅ Show or hide a field control
    formContext.getControl("telephone1").setVisible(false);

    // ✅ Disable a field (read-only)
    formContext.getControl("name").setDisabled(true);
}

2. Xrm.Navigation – Open Forms and Dialogs

Use Xrm.Navigation to open record forms, show alerts, or display confirmation dialogs to the user.

JavaScript Xrm.Navigation – Forms & Dialogs
// ✅ Open an existing record
Xrm.Navigation.openForm({
    entityName: "contact",
    entityId:   "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
});

// ✅ Open a new record form (no ID needed)
Xrm.Navigation.openForm({
    entityName: "account"
});

// ✅ Show a confirmation dialog
Xrm.Navigation.openConfirmDialog(
    { text: "Are you sure you want to proceed?" },
    { height: 200, width: 400 }
).then(function (result) {
    if (result.confirmed) {
        console.log("User clicked OK.");
    } else {
        console.log("User cancelled.");
    }
});

// ✅ Show a simple alert dialog
Xrm.Navigation.openAlertDialog({
    text:               "Record saved successfully.",
    confirmButtonLabel: "OK"
});

3. Xrm.Utility – Helper Functions

Use Xrm.Utility for common helper operations like showing a loading spinner, getting the logged-in user ID, or reading the organization URL.

JavaScript Xrm.Utility – Common Helpers
// ✅ Show a loading spinner while processing
Xrm.Utility.showProgressIndicator("Please wait, loading data...");

// ✅ Hide the loading spinner when done
Xrm.Utility.closeProgressIndicator();

// ✅ Get current logged-in user ID
var userId = Xrm.Utility.getGlobalContext().getUserId();
console.log("User ID: " + userId);

// ✅ Get current organization base URL
var orgUrl = Xrm.Utility.getGlobalContext().getClientUrl();
console.log("Org URL: " + orgUrl);

// ✅ Get current user security roles
var userRoles = Xrm.Utility.getGlobalContext().getUserRoles();
console.log("User Roles: " + userRoles);

📋 Step-by-Step Code Examples

1
Retrieve Multiple Records
🎯 Scenario: Fetch all active Account records and read their name, phone, and email.

This is the most common requirement in D365 development — fetching a list of records from Dataverse with specific fields and filter conditions. We use Xrm.WebApi.retrieveMultipleRecords with OData query options.

1
Build the OData query options

Use $select, $filter, $orderby, and $top to control what data you get.

2
Call retrieveMultipleRecords

Pass the entity name and your options string to the API.

3
Check if records were returned

Always check result.entities.length before trying to read data.

4
Loop and read each field

Use forEach to iterate and read the value of each field by its logical name.

5
Handle errors

Always add an error function — never leave .then() without one.

JavaScript retrieveMultipleRecords – Account Example
function getMultipleAccounts() {

    // Step 1 – Build the OData query options
    // $select  – only fetch the fields you need (never fetch all columns)
    // $filter  – statecode 0 = Active records only
    // $orderby – sort by name A to Z
    // $top     – limit to 50 records to avoid performance issues
    var options = "?$select=name,telephone1,emailaddress1,statecode" +
                  "&$filter=statecode eq 0" +
                  "&$orderby=name asc" +
                  "&$top=50";

    // Step 2 – Call retrieveMultipleRecords
    Xrm.WebApi.retrieveMultipleRecords("account", options).then(

        function success(result) {

            // Step 3 – Check if any records were returned
            if (result.entities.length === 0) {
                console.log("No active accounts found.");
                return;
            }

            console.log("Total Records Found: " + result.entities.length);
            console.log("===================================");

            // Step 4 – Loop through each record and read the field values
            result.entities.forEach(function (record) {

                var name   = record["name"]          || "Not Available";
                var phone  = record["telephone1"]    || "Not Available";
                var email  = record["emailaddress1"] || "Not Available";
                var status = record["statecode"] === 0 ? "Active" : "Inactive";

                console.log("Account Name : " + name);
                console.log("Phone        : " + phone);
                console.log("Email        : " + email);
                console.log("Status       : " + status);
                console.log("-----------------------------------");
            });
        },

        function error(err) {
            // Step 5 – Always handle errors
            console.error("Error fetching accounts: " + err.message);
            Xrm.Navigation.openAlertDialog({ text: "Error: " + err.message });
        }
    );
}
💡 Developer Tip: Always use $select to fetch only the fields you need. Fetching all columns is one of the most common performance mistakes in D365 JavaScript development. It slows your form down and consumes unnecessary API capacity.
2
Retrieve First Record – Reading All Field Types
🎯 Scenario: Fetch the first active Account and correctly read every field type — text, number, date, boolean, option set, and lookup.

This example is very important for beginners. Every field type in Dataverse is returned differently in the API response. You need to know exactly how to read each one to avoid bugs in your code.

JavaScript retrieveMultipleRecords – All Field Types ($top=1)
function getFirstAccount() {

    // Step 1 – Build the query
    // For lookup fields, use the _fieldname_value format in $select
    var options = "?$select=name,telephone1,emailaddress1," +
                  "revenue,numberofemployees,"    + // Number / Currency
                  "createdon,"                    + // Date field
                  "donotbulkemail,"               + // Boolean (Two Option)
                  "industrycode,"                 + // Option Set (Choice)
                  "_primarycontactid_value"        + // Lookup field
                  "&$filter=statecode eq 0" +
                  "&$top=1";                       // Only first record

    Xrm.WebApi.retrieveMultipleRecords("account", options).then(

        function success(result) {

            // Step 2 – Always check if record exists before reading
            if (result.entities.length === 0) {
                console.log("No record found.");
                return;
            }

            // Step 3 – Get the first item from the entities array
            var record = result.entities[0];

            // ✅ Text Field (Single Line of Text)
            var name  = record["name"];
            var phone = record["telephone1"];
            var email = record["emailaddress1"];
            console.log("Name  : " + name);
            console.log("Phone : " + phone);
            console.log("Email : " + email);

            // ✅ Number and Currency Fields
            var revenue   = record["revenue"];
            var employees = record["numberofemployees"];
            console.log("Revenue   : " + revenue);
            console.log("Employees : " + employees);

            // ✅ Date Field – Convert to readable local format
            var createdOn     = record["createdon"];
            var formattedDate = new Date(createdOn).toLocaleDateString("en-IN");
            console.log("Created On : " + formattedDate);

            // ✅ Boolean / Two Option Field
            var doNotEmail = record["donotbulkemail"];
            console.log("Do Not Email : " + (doNotEmail ? "Yes" : "No"));

            // ✅ Option Set / Choice Field
            // Raw value = integer stored in Dataverse
            // FormattedValue = the label the user sees on the form
            var industryCode = record["industrycode"];
            var industryName = record["industrycode@OData.Community.Display.V1.FormattedValue"];
            console.log("Industry (Value) : " + industryCode);
            console.log("Industry (Label) : " + industryName);

            // ✅ Lookup Field – Three pieces of information
            // 1. The GUID of the related record
            // 2. The display name shown to users
            // 3. The entity logical name of the related table
            var contactId   = record["_primarycontactid_value"];
            var contactName = record["_primarycontactid_value@OData.Community.Display.V1.FormattedValue"];
            var contactType = record["_primarycontactid_value@Microsoft.Dynamics.CRM.lookuplogicalname"];
            console.log("Contact ID     : " + contactId);
            console.log("Contact Name   : " + contactName);
            console.log("Contact Entity : " + contactType);
        },

        function error(err) {
            console.error("Error: " + err.message);
        }
    );
}

How to Read Lookup Fields – Explained Simply

Lookup fields return three separate pieces of information using OData annotations. Here is what each one gives you:

AnnotationWhat It ReturnsExample Value
_primarycontactid_valueThe GUID of the related recordxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
@OData.Community.Display.V1.FormattedValueThe display name shown to usersJohn Smith
@Microsoft.Dynamics.CRM.lookuplogicalnameThe logical name of the related entitycontact
💡 Developer Tip: For Option Set fields, always read both the raw value (industrycode) and the formatted label (@OData.Community.Display.V1.FormattedValue). The raw integer is used for comparisons in your logic. The label is used when displaying text to the user.
3
Retrieve a Single Record Directly by ID
🎯 Scenario: You have an Account ID from a lookup field on the form. Fetch that specific account's details directly.

When you already know the exact GUID of a record — for example from a lookup field on the current form — use retrieveRecord instead of retrieveMultipleRecords. It is faster, simpler, and more direct.

JavaScript retrieveRecord – Get One Record by GUID
function getSingleAccount(executionContext) {

    var formContext = executionContext.getFormContext();

    // Step 1 – Read the lookup field from the form
    var lookupValue = formContext.getAttribute("parentaccountid").getValue();

    // Step 2 – Check if a value is selected in the lookup
    if (lookupValue === null || lookupValue.length === 0) {
        console.log("No parent account selected on the form.");
        return;
    }

    // Step 3 – Lookup fields always return an array – use index [0]
    // Also remove curly braces from the GUID if present
    var accountId = lookupValue[0].id
                        .replace("{", "")
                        .replace("}", "");

    // Step 4 – Define the fields you want to fetch
    var options = "?$select=name,telephone1,emailaddress1,_primarycontactid_value";

    // Step 5 – Call retrieveRecord with entity name, GUID, and options
    Xrm.WebApi.retrieveRecord("account", accountId, options).then(

        function success(record) {

            var name        = record["name"];
            var phone       = record["telephone1"];
            var email       = record["emailaddress1"];
            var contactName = record["_primarycontactid_value@OData.Community.Display.V1.FormattedValue"];
            var contactId   = record["_primarycontactid_value"];

            console.log("Account Name : " + name);
            console.log("Phone        : " + phone);
            console.log("Email        : " + email);
            console.log("Contact Name : " + contactName);
            console.log("Contact ID   : " + contactId);
        },

        function error(err) {
            console.error("Error retrieving account: " + err.message);
        }
    );
}
💡 Developer Tip: Lookup field values on a Dynamics 365 form are always returned as an array, even when only a single record is selected. Always use lookupValue[0] to access the first selected record's ID, name, and entity type.

OData Query Options – Quick Reference

These are the query options you will use most often inside your Xrm.WebApi calls. Understanding them is essential for writing efficient D365 JavaScript.

OptionPurposeExample
$selectFetch only specific fields — always use this$select=name,telephone1
$filterFilter records by a condition$filter=statecode eq 0
$orderbySort results ascending or descending$orderby=name asc
$topLimit the number of records returned$top=50
$expandFetch fields from a related entity in the same call$expand=primarycontactid($select=fullname)

Active Records Filter

$filter=statecode eq 0

Inactive Records Filter

$filter=statecode eq 1

Filter by Text Field

$filter=name eq 'Contoso'

Filter by Lookup

$filter=_ownerid_value eq <GUID>


Key Takeaways

📌 Remember These Points

Always use Xrm.WebApi for all data operations — it is the official Microsoft standard for modern D365 development.
⚠️XMLHttpRequest is deprecated — avoid it completely in new development and plan to refactor it in older code.
Always use $select to limit the fields you fetch. Never retrieve all columns — it is the most common performance mistake.
Use $filter, $orderby, and $top to keep your queries efficient and results controlled.
For lookup fields, use the _fieldname_value format in $select and read three OData annotations to get the ID, display name, and entity type.
For option set fields, always read both the raw integer value and the FormattedValue annotation to get the readable label.
Always use executionContext.getFormContext() — never use the deprecated Xrm.Page object.
Always add an error handler in every WebApi call. Never leave .then() without an error function — silent failures are hard to debug.
Lookup field values from formContext are always returned as an array — always use lookupValue[0] to access the selected record.
✨ JavaScript in D365 might feel overwhelming at the start, but once you understand Xrm.WebApi and formContext, everything else starts to fall into place. Start small, test in the browser console, and build step by step. Every certified D365 developer started exactly where you are right now. Keep experimenting, keep building — and enjoy the journey. 🚀

📘 How to Create a SharePoint Site – Step-by-Step Guide

Introduction

SharePoint is a Microsoft platform used to store files, manage data, and help teams work together easily. If you are working with Power Platform or Dynamics 365, SharePoint is often used to store documents, manage lists, and share information across teams.

Creating a SharePoint site is simple, but understanding how it works makes it much easier to use later. In this guide, we will go step by step in a simple way.


What is a SharePoint Site?

A SharePoint site is like a workspace where you can store documents, manage data, share updates, and collaborate with your team.

It is commonly used for:

  • 📂 Document storage
  • 👥 Team collaboration
  • 📊 Data tracking using lists
  • ⚡ Power Platform integrations
  • 📢 Internal communication

Types of SharePoint Sites

👥 Team Site

Team Site is mainly used for collaboration. Teams use it to share files, track tasks, and work together on projects.

Common uses:

  • Project documents
  • Team data tracking
  • CRM document integration
  • Internal collaboration

Team Site Screenshot

📢 Communication Site

Communication Site is used to share information with a large group of people. It is more about announcements, news, or company updates rather than daily teamwork.

Common uses:

  • Company announcements
  • Internal portals
  • News updates
  • Department information sharing

Communication Site Screenshot


SharePoint vs Other Databases

Feature SharePoint Dataverse SQL Database
Document Storage Very Good Limited Not Recommended
Structured Data Good Excellent Excellent
Power Platform Integration Easy Native Needs Setup
Best Use Documents & Simple Data Business Applications Complex Data Systems

SharePoint Lists

A SharePoint List is like a table where you can store structured data. It works similarly to Excel but with more control, sharing, and automation support.

Common data types supported:

  • 📝 Single line text
  • 📄 Multiple line text
  • 🔢 Number
  • 📅 Date & Time
  • ✔ Yes/No
  • 👤 Person or Group
  • 📎 Attachment
  • 📊 Choice (Dropdown)
  • 🔗 Hyperlink

Lists are often used as a data source in Power Apps and Power Automate.


Document Library

A Document Library is where files are stored in SharePoint. You can upload documents, organize them, control permissions, and track version history.

It is commonly used for:

  • 📂 Document storage
  • 📑 Version tracking
  • 🔐 Permission control
  • 📎 Dynamics 365 document integration

SharePoint Document Library


How to Create a SharePoint Site (Step-by-Step)

Step 1 – Open SharePoint

Go to office.com, sign in, and open SharePoint from the app launcher.

SharePoint Screenshot

Step 2 – Click Create Site

You will see two options:

  • Team Site
  • Communication Site

Select the one that best suits your needs.

SharePoint Create Site Step Screenshot

Step 3 – Choose Template

Select a modern template from Microsoft, or go with the default Standard Team template.

SharePoint Template Selection Screenshot

Step 4 – Enter Site Details

Provide the following details while creating your SharePoint site:

  • Site Name – The name of your SharePoint site.
  • Description – Short info about the purpose of the site (optional but helpful).
  • Privacy Settings – Choose who can access the site:
    • Private – Only selected members can access the site.
    • Public – Anyone in your organization can view the site.
  • Language – Select your preferred site language (cannot be changed easily later).

SharePoint Site Detail Screenshot 1

SharePoint Site Detail Screenshot 2

Step 5 – Add Members

Add owners and members who will access the site.

SharePoint Site Screenshot

Click Finish, and your SharePoint site will be ready to use. Now you can create lists, upload documents, customize pages, and connect them with Power Platform or Dynamics 365.


Remember:

No need to make everything perfect from day one. Just start using SharePoint, try things out, and slowly you’ll get comfortable with it. 🙂

Getting Error Message While Switching Apps in Dynamics 365 (Missing Privilege Issue)

While working on a Dynamics 365 project, I faced a strange issue that looked serious at first, but in reality did not block any functionality. Still, it was confusing for users and needed to be fixed. In this post, I’ll explain what happened, why it happened, and how I resolved it.


The Issue

Some users reported that when they tried to switch apps within Dynamics 365, an error popup appeared on the screen.

Warning Message:
An error has occurred. Try this action again. If the problem continues, check the Microsoft Dynamics CRM Community for solutions or contact your organization's Microsoft Dynamics CRM Administrator. Finally, you can contact Microsoft Support.

Important points:

  • The error appeared during app switching
  • The app still loaded successfully
  • Users were able to continue their work
  • No functionality was broken

So technically nothing failed, but the popup confused users.

Dynamics 365 error popup while switching apps

Why This Was a Problem

Even though users could continue working, the error message:

  • Created confusion
  • Made users think something was wrong
  • Generated unnecessary support questions

From a project and user experience point of view, this was not something to ignore.


Initial Checks

I started with basic troubleshooting:

  • Browser console logs
  • Network tab
  • Plugin trace logs

Nothing useful showed up. No clear error, no table name, no hint. That’s when it became clear this was most likely a security-related issue.


Observing the Pattern

After testing with different users, one pattern was clear:

  • Users with custom security roles saw the error
  • System Administrators did not

This confirmed that the issue was related to security roles.

Dynamics 365 app switching screen error

Root Cause: Missing Privilege in Custom Security Role

After reviewing the custom security role, I found the issue.

One of the tables required by the app did not have Read permission for that role.

Even though:

  • The table was not directly used by the user
  • The app still opened

Dynamics 365 checks access to required tables during app loading. If any required privilege is missing, it may show a generic error popup.

This missing privilege was not captured in the browser console, which made debugging harder.

Dynamics 365 security role missing read privilege

How I Fixed It

Once the cause was clear, the fix was simple.

  1. Go to Settings → Security → Security Roles
  2. Open your custom security role
  3. Search for the Role table (Display Name: Security Role)
  4. Provide Read permission at Global level
  5. Save and publish the security role
  6. Ask the user to refresh the browser and switch the app again

After this change, the error popup stopped appearing.


Tips to Avoid This Issue

  • Always test apps using real business user roles
  • Review security roles when new apps or components are added
  • If no console error appears, check security roles first
  • Compare working and non-working roles to spot missing privileges
  • Do not ignore error popups even if functionality works

Related Reading

If you want to understand how apps and permissions work in Power Platform, you can also read this:

👉 Get started with Microsoft Canvas App
👉 How to Get and Set Field Values in Dynamics 365 CRM using JavaScript

Get Started with Microsoft Canvas App

Microsoft Canvas App – A Practical Guide for Power Platform Developers

Canvas Apps are one of the most flexible offerings in the Microsoft Power Platform. They allow developers to design custom user experiences using a low-code approach while still supporting complex business logic.

This blog explains what a Canvas App is, where it excels, where it struggles, real-world use cases, supported data sources, and provides a comprehensive overview of components and Power Fx functions, accompanied by brief explanations.

Canvas App Overview


What is a Canvas App?

A Canvas App lets you design your app screen-by-screen with full control over layout and behavior. You place controls like labels, buttons, galleries, and forms wherever you want and define logic using Power Fx.

Canvas Apps are UI-first, making them perfect for mobile apps, custom workflows, and task-based solutions.


What Makes Canvas Apps Awesome

  • Full control over UI and user experience
  • Rapid development with low-code formulas
  • Works well for mobile-first and custom apps
  • Supports many data sources beyond Dataverse
  • Easy integration with Power Automate

Where Canvas Apps Fall Short (Compared to Model-Driven Apps)

  • Handling complex relational data is harder
  • No built-in business process flows
  • Security must be handled manually in some cases
  • Performance can degrade with large datasets

Business Scenarios – When to Use Canvas Apps

  • Field inspection and survey apps
  • Employee self-service portals
  • Approval and request management
  • Inventory and asset tracking
  • Custom mobile apps for sales teams

Data Sources Supported by Canvas Apps

  • Dataverse
  • SharePoint
  • Excel (OneDrive / SharePoint)
  • SQL Server (Azure & On-Prem via Gateway)
  • Microsoft Lists
  • Dynamics 365
  • Custom APIs using Custom Connectors

Canvas App Components (Purpose + Working)

Label

Displays static or dynamic text on the screen.


Text = "Hello " & User().FullName

Text Input

Accepts user input such as names, emails, or numbers.


TextInput1.Text

Button

Triggers an action when clicked.


OnSelect = SubmitForm(Form1)

Gallery

Shows a list of records in a repeating layout.


Items = Employees

Form (Edit / Display)

Used to create, update, or view records.


DataSource = Employees

Dropdown

Allows selection of a single value from a list.


Items = Distinct(Employees, Department)

ComboBox

Advanced dropdown with multi-select and search.


SelectedItems

Date Picker

Lets users select a date.


SelectedDate

Toggle

Captures Yes/No input.


Toggle1.Value

Checkbox

Used for boolean selections.


Checkbox1.Value

Icon

Clickable icon used for actions.


OnSelect = Remove(Employees, ThisItem)

Timer

Runs logic after a set time interval.


OnTimerEnd = Refresh(Employees)

Component (Custom)

Reusable UI with encapsulated logic.


Input / Output properties


Top 25 Most Used Power Fx Functions

1. Patch

Creates or updates records in a data source.


Patch(DS, Defaults(DS), {Name:"Ajay"})

2. SubmitForm

Saves form data to the connected data source.


SubmitForm(Form1)

3. Collect

Adds records to a local collection.


Collect(colData, DS)

4. ClearCollect

Clears and reloads a collection.


ClearCollect(colData, DS)

5. Filter

Returns records that meet a condition.


Filter(DS, Status="Active")

6. LookUp

Finds the first matching record.


LookUp(DS, Email=User().Email)

7. Remove

Deletes a specific record.


Remove(DS, ThisItem)

8. RemoveIf

Deletes records based on condition.


RemoveIf(DS, Status="Inactive")

9. UpdateIf

Updates records conditionally.


UpdateIf(DS, Status="New", {Status:"Closed"})

10. If

Runs logic based on conditions.


If(IsBlank(txt.Text), Notify("Required"))

11. Switch

Executes logic based on multiple conditions.


Switch(Role, "Admin", true, false)

12. Navigate

Navigates to another screen.


Navigate(Screen2)

13. Notify

Displays in-app notifications.


Notify("Saved", NotificationType.Success)

14. Set

Creates or updates global variables.


Set(varUser, User().Email)

15. UpdateContext

Creates screen-level variables.


UpdateContext({locVisible:true})

16. Concurrent

Runs multiple actions in parallel.


Concurrent(Refresh(A), Refresh(B))

17. IsBlank

Checks if a value is blank.


IsBlank(TextInput1.Text)

18. IsEmpty

Checks if a table or collection is empty.


IsEmpty(colData)

19. CountRows

Counts records in a table.


CountRows(Gallery1.AllItems)

20. Sum

Calculates total of numeric values.


Sum(Sales, Amount)

21. Text

Formats values as readable text.


Text(Today(), "dd-mm-yyyy")

22. Value

Converts text to numeric value.


Value(TextInput1.Text)

23. Today

Returns current system date.


Today()

24. Now

Returns current date and time.


Now()

25. Refresh

Reloads latest data from source.


Refresh(DS)

Remember, every great Canvas App started with a single control on a blank screen. Experiment, explore, and don't be afraid to try new ideas.

Keep learning, keep creating, and enjoy the ride! 🌟



🌐 Understanding Dynamics 365 CE & Dataverse

 Whether you're just starting your journey as a Dynamics 365 Developer or preparing for that big interview, everything begins with a clear understanding of what you're actually building on. That means understanding what Dynamics 365 CE is, and more importantly, how Dataverse holds it all together.

Let’s break it down.

💡 What is Dynamics 365 CE?

When we say Dynamics 365 Customer Engagement (CE), we’re talking about a collection of Microsoft business applications focused on managing customer-facing processes. Think about:

  • 💼 Sales – for tracking leads, opportunities, and closing deals

  • 🎧 Customer Service – for handling cases, SLAs, and knowledge management

  • 📣 Marketing – for managing campaigns, segments, customer journeys

  • 🧰 Field Service – for dispatching technicians and managing assets

  • 📊 Project Operations – for managing resource utilization and project billing

All of these apps don’t live in isolation. They run on a shared platform called Dataverse.


🧠 So, What Exactly Is Dataverse?

You can think of Dataverse as the "database with superpowers."

It's not just where data is stored — it's the backbone of all Power Platform applications and Dynamics 365 CE modules. It handles things like:

  • Tables (Entities) – like Contact, Account, or Case

  • Relationships – one-to-many, many-to-many

  • Security roles & access control

  • Business logic – workflows, business rules, calculated fields

  • APIs – for developers to read/write/update data

🔍 Fun Fact: Dataverse was formerly known as Common Data Service (CDS). Microsoft rebranded it, but many principles are the same.


🏗️ Dataverse = A Developer’s Playground

If you're a D365 developer, here’s what makes Dataverse special for you:

  • You can customize tables, fields, and relationships without writing code.

  • You can write plugins to run server-side logic during operations like create/update/delete.

  • You can integrate external systems using the Web API or the SDK.

  • You can build rich Power Automate flows or Power Apps that talk directly to Dataverse.

In other words, it gives you the flexibility of a relational database with the power of a business platform.


🔐 Security Model in Dataverse

Security isn’t an afterthought — it’s baked in.

Dataverse provides a layered security model:

  • Business Units – Logical segregation of users (e.g., by department or geography)

  • Security Roles – Define what actions a user can perform (Read, Write, Delete, etc.)

  • Teams – Users can belong to multiple teams and inherit access

  • Hierarchy Security – Managers can access records of their reports

🛡️ This model ensures that data access is well-governed — a crucial need for enterprise-grade apps.


💬 Real-World Analogy

Imagine you're building an app to manage real estate assets. Dataverse lets you:

  • Create a A Property table with custom columns like Area, Price, Location

  • Link each property to an Owner (Account)

  • Restrict certain users to only see properties in their city (via business units)

  • Run a plugin to auto-calculate stamp duty based on the price

All of this happens inside Dataverse, without needing to build your own backend from scratch.


🎯 Interview Questions

1. What are the core components of the Power Platform?
Ans. Power Apps, Power Automate, Power BI, Power Pages, and Dataverse.

2. What is Dataverse?
Ans. Cloud-based data platform for storing and managing business data.

3. Difference between Dataverse and traditional SQL?
Ans. Dataverse offers metadata-driven logic, relationships, security, and integration support.

4. How is metadata stored and managed in Dataverse?
Ans. Metadata (like table schema, relationships) is stored in system tables and drives the platform's dynamic behavior.

5. What’s the difference between model-driven and canvas apps?
Ans. Model-driven apps are data-first (based on Dataverse), canvas apps are design-first (pixel control).

6. What’s the role of business units?
Ans. They define the data access boundary for users.

7. What is a business unit in D365 CE and how does it impact data access?
Ans. It creates a hierarchy that controls the visibility of records to users based on their assigned unit.

8. Can we control field-level security in Dataverse?
Ans. Yes, via Field Security Profiles

9. What is the difference between record ownership and access?
Ans. Ownership gives control over a record; access (via sharing, role, or team) allows interaction without owning.

10. What are Access Teams vs Owner Teams?
Ans. Owner Teams own records; Access Teams are temporary and used for granting record-level access dynamically.

11. What is the role of a solution in D365 CE?
Ans. A container to group and transport customizations like tables, fields, views, and flows.

12. Managed vs Unmanaged solutions?
Ans. Managed = for deployment, Unmanaged = for development.

13. Can we export a solution with data? If yes, how?
Ans. No, solutions don’t carry data. Use Data Export Service, Azure Data Factory, or dataflows.

14. What is patching in managed solutions?
Ans. Patches allow delivering small updates over a base managed solution, useful for hotfixes.

15. What is the difference between a patch and a clone of a solution?
Ans. A patch makes a small update to an existing solution; a clone creates a new major version that includes all prior patches.

16. Can you export a managed solution from a production environment?
Ans. No, only unmanaged solutions can be exported. Managed solutions are meant for deployment, not modification.

17. What happens if two managed solutions customize the same component?
Ans. The solution installed last wins (layering). Managed conflicts are resolved via solution layering.

18. What happens when you delete a managed solution from an environment?
Ans. All components included in that solution (that weren’t used elsewhere) are removed, making it risky in production.

18. Can you explain the solution layering model in D365 CE?
Ans. D365 uses a layered solution model:
        System Layer → Managed → Unmanaged.
        The top-most layer takes precedence.

19. What are polymorphic lookups in Dataverse (also called Customer or Regarding)?
Ans. These allow referencing more than one type of table (e.g., Customer can link to either Account or Contact).

20. Which APIs can developers use to access Dataverse?
Ans. Web API (REST), SDK via IOrganizationService (SOAP), and Data Export (for external sync).

21. What are some limitations of Dataverse developers should be aware of?
Ans. Some key limitations:
  • API limits (service protection throttling)
  • Complex joins are harder than in SQL
  • Plugin execution timeout (~2 minutes)
  • Storage can become expensive at scale



How to Get and Set Field Values in Dynamics 365 CRM using JavaScript

Customizing Dynamics 365 CRM using JavaScript allows you to dynamically retrieve and update field values, improving user experience and automation. This blog provides JavaScript examples for getting and setting different field types in Dynamics 365.

Getting Started

To begin, use the following function to get the form context:


function GetSet(executionContext) {
    var formContext = executionContext.getFormContext();
}

Now, let's explore different field types and how to work with them.

How to Get Latitude and Longitude from an Address Using Bing Maps API in JavaScript for D365

 

Getting Latitude & Longitude from an Address Using Bing Maps API


In Microsoft Dynamics 365, capturing latitude and longitude based on a given address is crucial for various business scenarios, such as the following:

  • Customer Location Tracking: Storing precise geolocation details for customers.

  • Field Service Optimization: Assigning technicians based on customer locations.

  • Sales Territory Management: Mapping sales territories.

To achieve this, we use the Bing Maps API to convert an input address into geographic coordinates (latitude and longitude) and auto-populate them in Dynamics 365 fields.