Total Number of Record : RetrieveTotalRecordCount

A very common request by customer is to get total number of record in D365 system for a given entities. It is pretty straight forward for D365 On Prem, you can do a count on SQL DB. But for D365 online you either need to rely on XrmToolBox fetch counter(which can still be used) or aggregrate function or even on DES database. However we do have a simple way now : RetrieveTotalRecordCount

I have all the entities in my system stored in a text file. The C# code to get count of all the entities will be like this:

            string[] entitylist = File.ReadLines(@"D:\entitylist.txt").ToArray();
            var client = new CdsServiceClient(connectionString);// I am using .NET core. Change it to var client = new CrmServiceClient(connectionString);           
            RetrieveTotalRecordCountRequest req = new RetrieveTotalRecordCountRequest
            {
                EntityNames = entitylist
            };
            EntityRecordCountCollection m = ((RetrieveTotalRecordCountResponse)client.Execute(req)).EntityRecordCountCollection;
            long count = 0;
            foreach (var i in m)
            {
                Console.WriteLine(i.Key + " =" + i.Value);
                count += i.Value;
            }
            Console.WriteLine(@$"Count ={count}");

I was having around 600 entitites with 200 million records in total and it took 2 second to get the result. So pretty sure its doing SQL count underneath.

If you are using POSTMAN – just use below url

GET {{webapiurl}}/RetrieveTotalRecordCount(EntityNames=[‘contact’,’account’])

and it ifs JS then just change pass the same request as above using webAPI.

function GetTotalCount(executionContext)
{
	var formContext = executionContext.getFormContext();
    var req = new XMLHttpRequest();
    req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/RetrieveTotalRecordCount(EntityNames="+JSON.stringify(['contact','account']) +")", true);
    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.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");
    req.onreadystatechange = function() {
        if (this.readyState === 4) {
            req.onreadystatechange = null;
            if (this.status === 200) {
                var results = JSON.parse(this.response);
                for (var i = 0; i < results.EntityRecordCountCollection.Count; i++) {
                    var value = results.EntityRecordCountCollection.Values[i];
                    alert(results.EntityRecordCountCollection.Keys[i] + " = "+ value);
                }
            } else {
                Xrm.Utility.alertDialog(this.statusText);
            }
        }
    };
    req.send();
}

https://docs.microsoft.com/en-us/dynamics365/customer-engagement/web-api/retrievetotalrecordcount?view=dynamics-ce-odata-9

We still dont have a way to apply a filter and then get the count directly. Hoping to get this feature in future.

Qualify Lead using Web API with Existing Contact

If you want to qualify a lead using WebAPI, the message is Microsoft.Dynamics.CRM.QualifyLead.

https://docs.microsoft.com/en-us/dynamics365/customer-engagement/web-api/qualifylead?view=dynamics-ce-odata-9

If you dont want to create account/contact but in turn link it with existing customer – you can use something like this:

POST https://<org>.crm.dynamics.com/api/data/v9.0/leads(<leadid>)/Microsoft.Dynamics.CRM.QualifyLead

BODY:

{
   "CreateAccount":false,
   "CreateContact":false,
   "CreateOpportunity":true,
   "OpportunityCustomerId":{"@odata.type":"Microsoft.Dynamics.CRM.contact","contactid":"34289935-9A54-EB11-A812-000D3A8B898C"},
   "Status":-1,
   "SuppressDuplicateDetection":true
}

I was however not able to pass both account and contact – so if the lead has already ‘Existing Account’ field filled and you pass the contact in webAPI call, then you will get both account and contact filled in the opportunity record.

function qualifyLeadwithContact(leadId, contactid, clientUrl) {
    try {
        var request = "leads(" + leadId.replace("}", "").replace("{", "") + ")/Microsoft.Dynamics.CRM.QualifyLead";
        var postdata = {
			"CreateAccount":false,
			"CreateContact":false,
			"CreateOpportunity":true,
			"OpportunityCustomerId":{"@odata.type":"Microsoft.Dynamics.CRM.contact","contactid":contactid},
			"Status":-1,
			"SuppressDuplicateDetection":true
				};
        var req = new XMLHttpRequest();
        req.open("POST", clientUrl + "/api/data/v9.0/" + request, true);
        req.setRequestHeader("Accept", "application/json");
        req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        req.setRequestHeader("OData-MaxVersion", "4.0");
        req.setRequestHeader("OData-Version", "4.0");

        req.onreadystatechange = function () {

            if (this.readyState == 4) {
                req.onreadystatechange = null;

                if (this.status == 200 || this.status == 204) {
                    var result = JSON.parse(this.response);

                } else {
                    var error = JSON.parse(this.response).error;
                }
            }
        };
        req.send(JSON.stringify(postdata));

    } catch (e) {
        throwError(functionName, e);
    }
}

CRUD operation on Single Page Application for D365 using MSAL with jqGrid

We are re-creating our SPA but using MSAL instead of ADAL. MSAL allow authentication using wider set of identities instead of just Azure AD as for ADAL. The list of differences can be found here.

Below is the sample code for performing CRUD operation in jqGrid for D365 using MSAL.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/themes/redmond/jquery-ui.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.4/css/ui.jqgrid.min.css">
    <a href="https://alcdn.msauth.net/browser/2.0.0-beta.4/js/msal-browser.js">https://alcdn.msauth.net/browser/2.0.0-beta.4/js/msal-browser.js</a>
    <a href="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js">https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js</a>
    <a href="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.4/jquery.jqgrid.min.js">https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.4/jquery.jqgrid.min.js</a>
    <script type="text/javascript">
        const msalConfig = {
            auth: {
                clientId: "xxxxxxxxx-f8d4-448b-ba96-e3097cd7c3dd",
                authority: "https://login.microsoftonline.com/common",
                redirectUri: "https://localhost:44308/SinglePageAppMSAL.html"
            },
            cache: {
                cacheLocation: "sessionStorage", // This configures where your cache will be stored
                storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
            },
            system: {
                loggerOptions: {
                    loggerCallback: (level, message, containsPii) => {
                        if (containsPii) {
                            return;
                        }
                        switch (level) {
                            case msal.LogLevel.Error:
                                console.error(message);
                                return;
                            case msal.LogLevel.Info:
                                console.info(message);
                                return;
                            case msal.LogLevel.Verbose:
                                console.debug(message);
                                return;
                            case msal.LogLevel.Warning:
                                console.warn(message);
                                return;
                        }
                    }
                }
            }
        };

        const loginRequest = {
            scopes: ["https://xxxxxxxxxxxxx.crm.dynamics.com/.default"]
        };


        const tokenRequest = {
            scopes: ["https://xxxxxxxxxxxxx.crm.dynamics.com/.default"],
            forceRefresh: false // Set this to "true" to skip a cached token and go to the server to get a new token
        };


        const myMSALObj = new msal.PublicClientApplication(msalConfig);
        let accessToken;
        let username = "";

        myMSALObj.handleRedirectPromise().then(handleResponse).catch(err => {
            console.error(err);
        });

        function handleResponse(resp) {
            if (resp !== null) {
                username = resp.account.username;
                loginButton.style.display = "none";
                logoutButton.style.display = "block";
                getAccountsButton.style.display = "block";

                var helloMessage = document.createElement("p");
                helloMessage.textContent = "Hello " + username;
                message.appendChild(helloMessage);
            }
            else {
                const currentAccounts = myMSALObj.getAllAccounts();
                if (currentAccounts === null) {

                    return;
                } else if (currentAccounts.length > 1) {
                    // Add choose account code here
                    console.warn("Multiple accounts detected.");
                } else if (currentAccounts.length === 1) {
                    username = currentAccounts[0].username;
                }
            }
        }

        function signIn() {
            myMSALObj.loginRedirect(loginRequest);            
        }

        function signOut() {
            const logoutRequest = {
                account: myMSALObj.getAccountByUsername(username)
            };
            myMSALObj.logout(logoutRequest);
        }

        function getTokenRedirect(request) {
            request.account = myMSALObj.getAccountByUsername(username);
            return myMSALObj.acquireTokenSilent(request).catch(error => {
                console.warn("silent token acquisition fails. acquiring token using redirect");
                if (error instanceof msal.InteractionRequiredAuthError) {
                    return myMSALObj.acquireTokenRedirect(request);
                } else {
                    console.warn(error);
                }
            });
        }

        function readAccount() {
            getTokenRedirect(tokenRequest).then(response => {
                retrieveAccounts(response.accessToken);
            }).catch(error => {
                console.error(error);
            });
        }

        function renderAccount(accounts, token) {
            $("#grid").clearGridData();
            var listOfAccounts = [];
            accounts.forEach(function (account) {
                var name = account.name;
                var city = account.address1_city;
                var accountid = account.accountid;
                listOfAccounts.push({
                    name: name,
                    city: city,
                    accountid: accountid
                });
            });
            $("#grid").jqGrid({
                colModel: [
                    { name: "name", width: 300, editable: true },
                    { name: "city", width: 300, editable: true },
                    { name: "accountid", width: 300, editable: true, editrules: { edithidden: false }, hidden: true },
                ],
                pager: '#pager2',
                sortname: 'name',
                viewrecords: true,
                sortorder: "desc",
                caption: "",
                editable: true,
                data: listOfAccounts
            });
            $("#grid").setGridParam({ data: listOfAccounts }).trigger("reloadGrid");
            $("#grid").jqGrid('navGrid', '#pager2',
                {
                    edit: true,
                    add: true,
                    del: true,
                    search: false,
                    refresh: false,
                    view: false
                },
                {
                    editCaption: "Edit Account",
                    edittext: "Edit",
                    closeOnEscape: true,
                    closeAfterEdit: true,
                    savekey: [true, 13],
                    errorTextFormat: commonError,
                    reloadAfterSubmit: true,
                    onclickSubmit: function (response, postdata) {
                        if (confirm('Are you sure you want to update this row?')) {
                            UpdateAccount(postdata, token);
                            return [true, ''];
                        } else {
                            return [false, 'You can not submit!'];
                        }
                    }
                },
                {
                    addCaption: "Add Account",
                    addtext: "Add Account",
                    closeAfterAdd: true,
                    recreateForm: true,
                    errorTextFormat: commonError,
                    onclickSubmit: function (response, postdata) {
                        postdata.accountid = AddAccount(postdata, token);
                    }
                },
                {
                    deleteCaption: "delete Account",
                    deletetext: "Delete Account",
                    closeOnEscape: true,
                    closeAfterEdit: true,
                    savekey: [true, 13],
                    errorTextFormat: commonError,
                    reloadAfterSubmit: true,
                    onclickSubmit: function (response, postdata) {
                        var sr = jQuery("#grid").getGridParam('selrow');
                        var rowdata = jQuery("#grid").getRowData(sr);
                        DeleteAccount(rowdata, token);
                    }
                },
                {},
            );
        }

        function retrieveAccounts(token) {
            if (!token) {
                errorMessage.textContent = 'error occurred: ';
                return;
            }
            
            var req = new XMLHttpRequest()
            req.open("GET", encodeURI("https://xxxxxxxxxxxxx.crm.dynamics.com/api/data/v9.1/accounts?$select=name,address1_city,accountid&$top=10"), true);
            req.setRequestHeader("Authorization", "Bearer " + token);
            req.setRequestHeader("Accept", "application/json");
            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            req.setRequestHeader("OData-MaxVersion", "4.0");
            req.setRequestHeader("OData-Version", "4.0");
            req.onreadystatechange = function () {
                if (this.readyState == 4 /* complete */) {
                    req.onreadystatechange = null;
                    if (this.status == 200) {
                        var account = JSON.parse(this.response).value;
                        renderAccount(account, token);
                    }
                    else {
                        var error = JSON.parse(this.response).error;
                        console.log(error.message);
                        errorMessage.textContent = error.message;
                    }
                }
            };
            req.send();
        }


        function UpdateAccount(params, token) {
            var req = new XMLHttpRequest();
            req.open("PATCH", encodeURI("https://xxxxxxxxxxxxx.crm.dynamics.com/api/data/v9.1/accounts(" + params.accountid + ")"), false);
            req.setRequestHeader("Authorization", "Bearer " + token);
            req.setRequestHeader("Accept", "application/json");
            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            req.setRequestHeader("OData-MaxVersion", "4.0");
            req.setRequestHeader("OData-Version", "4.0");
            var body = JSON.stringify({
                "name": params.name,
                "address1_city": params.city
            });
            req.send(body);
            if (req.readyState === 4) {
                if (req.status === 204) {
                    var uri = req.getResponseHeader("OData-EntityId");
                    var regExp = /\(([^)]+)\)/;
                    var matches = regExp.exec(uri);
                    var accountid = matches[1];
                    alert(params.name + " Updated");
                }
                else {
                    var error = JSON.parse(req.response).error;
                    alert(error.message);
                }
            }
        }

        function AddAccount(params, token) {
            var account = {};
            account["name"] = params.name;
            account["address1_city"] = params.city;
            var req = new XMLHttpRequest();
            req.open("POST", encodeURI("https://xxxxxxxxxxxxx.crm.dynamics.com/api/data/v9.1/accounts"), false);
            req.setRequestHeader("Authorization", "Bearer " + token);
            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(JSON.stringify(account));
            if (req.readyState === 4) {
                if (req.status === 204) {
                    var uri = req.getResponseHeader("OData-EntityId");
                    var regExp = /\(([^)]+)\)/;
                    var matches = regExp.exec(uri);
                    var accountid = matches[1];
                    alert(params.name + " Created");
                    return accountid;
                }
                else {
                    var error = JSON.parse(req.response).error;
                    alert(error.message);
                }
            }
        }

        function DeleteAccount(params, token) {
            var req = new XMLHttpRequest();
            req.open("DELETE", encodeURI("https://xxxxxxxxxxxxx.crm.dynamics.com/api/data/v9.1/accounts(" + params.accountid + ")"), false);
            req.setRequestHeader("Authorization", "Bearer " + token);
            req.setRequestHeader("Accept", "application/json");
            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            req.setRequestHeader("OData-MaxVersion", "4.0");
            req.setRequestHeader("OData-Version", "4.0");
            req.send();
            if (req.readyState === 4) {
                if (req.status === 204) {
                    alert(params.name + " Deleted");
                }
                else {
                    var error = JSON.parse(req.response).error;
                    alert(error.message);
                }
            }
        }

        function commonError(data) {
            return "Error Occured during Operation. Please try again";
        }
        document.onreadystatechange = function () {
            if (document.readyState == "complete") {

                //Set DOM elements referenced by scripts
                message = document.getElementById("message");
                errorMessage = document.getElementById("errorMessage");
                loginButton = document.getElementById("login");
                logoutButton = document.getElementById("logout");
                getAccountsButton = document.getElementById("getAccounts");

                //Event handlers on DOM elements
                loginButton.addEventListener("click", signIn);
                logoutButton.addEventListener("click", signOut);
                getAccountsButton.addEventListener("click", readAccount);

                if (username) {
                    loginButton.style.display = "none";
                    logoutButton.style.display = "block";
                    getAccountsButton.style.display = "block";

                    var helloMessage = document.createElement("p");
                    helloMessage.textContent = "Hello " + username;
                    message.appendChild(helloMessage)

                }
                else {
                    loginButton.style.display = "block";
                    logoutButton.style.display = "none";
                    getAccountsButton.style.display = "none";
                }
            }
        }
    </script>
    <style>
        body {
            font-family: 'Segoe UI';
        }

        table {
            border-collapse: collapse;
        }

        td, th {
            border: 1px solid black;
        }

        #errorMessage {
            color: red;
        }

        #message {
            color: green;
        }
    </style>
</head>
<body>
    <button id="login">Login</button>
    <button id="logout" style="display:none;">Logout</button>
    <button id="getAccounts" style="display:none;">Get Accounts</button>
    <div id="errorMessage"></div>
    <div id="message"></div>
    <table id="grid"></table>
    <div id="pager2"></div>
</body>
</html>

Single Page Application(SPA) – CRUD operation in D365 using jqGrid

Below is the sample code to create a SPA to perform CRUD operation on D365 using WebAPI and ADAL for authentication. The code demonstrate use of GET, POST, PATCH and DELETE for Retrieve, Create, Update and Delete respectively. The sample code provided from Microsoft is used here as base and additional feature are added on top of it.

<!DOCTYPE html>
<html>
<head>
    <title>D365 Single Page Application for D365 using jqGrid</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/themes/redmond/jquery-ui.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.4/css/ui.jqgrid.min.css">
    <a href="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.17/js/adal.min.js">https://secure.aadcdn.microsoftonline-p.com/lib/1.0.17/js/adal.min.js</a>
    <a href="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js">https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js</a>
    <a href="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.4/jquery.jqgrid.min.js">https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.4/jquery.jqgrid.min.js</a>

    <script type="text/javascript">
        "use strict";
        var organizationURI = "https://xxxx.crm.dynamics.com"; //The URL of your Dataverse organization
        var tenant = "xxxx.onmicrosoft.com"; //The name of the Azure AD organization you use
        var clientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; //The ClientId you got when you registered the application
        var pageUrl = "https://localhost:44347/SHtmlPage.html"; //The URL of this page in your development environment when debugging.

        var user, authContext, message, errorMessage, loginButton, logoutButton, getAccountsButton;

        //Configuration data for AuthenticationContext
        var endpoints = {
            orgUri: organizationURI
        };

        window.config = {
            tenant: tenant,
            clientId: clientId,
            postLogoutRedirectUri: pageUrl,
            endpoints: endpoints,
            cacheLocation: 'localStorage',
        };

        document.onreadystatechange = function () {
            if (document.readyState == "complete") {

                //Set DOM elements referenced by scripts
                message = document.getElementById("message");
                errorMessage = document.getElementById("errorMessage");
                loginButton = document.getElementById("login");
                logoutButton = document.getElementById("logout");
                getAccountsButton = document.getElementById("getAccounts");

                //Event handlers on DOM elements
                loginButton.addEventListener("click", login);
                logoutButton.addEventListener("click", logout);
                getAccountsButton.addEventListener("click", getAccounts);

                //call authentication function
                authenticate();

                if (user) {
                    loginButton.style.display = "none";
                    logoutButton.style.display = "block";
                    getAccountsButton.style.display = "block";

                    var helloMessage = document.createElement("p");
                    helloMessage.textContent = "Hello " + user.profile.name;
                    message.appendChild(helloMessage)

                }
                else {
                    loginButton.style.display = "block";
                    logoutButton.style.display = "none";
                    getAccountsButton.style.display = "none";
                }

            }
        }

        // Function that manages authentication
        function authenticate() {
            //OAuth context
            authContext = new AuthenticationContext(config);

            // Check For & Handle Redirect From AAD After Login
            var isCallback = authContext.isCallback(window.location.hash);
            if (isCallback) {
                authContext.handleWindowCallback();
            }
            var loginError = authContext.getLoginError();

            if (isCallback && !loginError) {
                window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST);
            }
            else {
                errorMessage.textContent = loginError;
            }
            user = authContext.getCachedUser();

        }

        //function that logs in the user
        function login() {
            authContext.login();
        }
        //function that logs out the user
        function logout() {
            authContext.logOut();
        }

        //function that initiates retrieval of accounts
        function getAccounts() {
            getAccountsButton.disabled = true;
            var retrievingAccountsMessage = document.createElement("p");
            retrievingAccountsMessage.textContent = "Retrieving 10 accounts from " + organizationURI + "/api/data/v9.1/accounts";
            message.appendChild(retrievingAccountsMessage)

            // Function to perform operation is passed as a parameter to the acquireToken method
            authContext.acquireToken(organizationURI, retrieveAccounts)
        }

        //Function that actually retrieves the accounts
        

        function renderAccounts(accounts, token) {
            var listOfAccounts = [];
            accounts.forEach(function (account) {
                var name = account.name;
                var city = account.address1_city;
                var accountid = account.accountid;
                listOfAccounts.push({
                    name: name,
                    city: city,
                    accountid: accountid
                });
            });

            $("#grid").jqGrid({
                colModel: [
                    { name: "name", width: 300, editable: true},
                    { name: "city", width: 300, editable: true },
                    { name: "accountid", width: 300, editable: true, editrules: { edithidden: false }, hidden: true },
                ],
                pager: '#pager2',
                sortname: 'name',
                viewrecords: true,
                sortorder: "desc",
                caption: "",
                editable: true,
                data: listOfAccounts
            });
            $("#grid").jqGrid('navGrid', '#pager2',
                {
                    edit: true,
                    add: true,
                    del: true,
                    search: false,
                    refresh: false,
                    view: false
                },
                {
                    editCaption: "Edit Account",
                    edittext: "Edit",
                    closeOnEscape: true,
                    closeAfterEdit: true,
                    savekey: [true, 13],
                    errorTextFormat: commonError,
                    reloadAfterSubmit: true,
                    onclickSubmit: function (response, postdata) {
                        if (confirm('Are you sure you want to update this row?')) {
                            UpdateAccount(postdata, token);
                            return [true, ''];
                        } else {
                            return [false, 'You can not submit!'];
                        }
                    }
                },
                //add Options. save key parameter will keybind the Enter key to submit.
                {
                    addCaption: "Add Account",
                    addtext: "Add Account",
                    closeAfterAdd: true,
                    recreateForm: true,
                    errorTextFormat: commonError,
                    onclickSubmit: function (response, postdata) {
                        postdata.accountid = AddAccount(postdata, token);
                    }
                },
                {
                    deleteCaption: "delete Account",
                    deletetext: "Delete Account",
                    closeOnEscape: true,
                    closeAfterEdit: true,
                    savekey: [true, 13],
                    errorTextFormat: commonError,
                    reloadAfterSubmit: true,
                    onclickSubmit: function (response, postdata) {
                        var sr = jQuery("#grid").getGridParam('selrow');
                        var rowdata = jQuery("#grid").getRowData(sr);
                        DeleteAccount(rowdata, token);
                    }
                },
                {},
            );
        }
        
        function retrieveAccounts(error, token) {
            // Handle ADAL Errors.
            if (error || !token) {
                errorMessage.textContent = 'ADAL error occurred: ' + error;
                return;
            }

            var req = new XMLHttpRequest()
            req.open("GET", encodeURI(organizationURI + "/api/data/v9.1/accounts?$select=name,address1_city,accountid&$top=10"), true);
            req.setRequestHeader("Authorization", "Bearer " + token);
            req.setRequestHeader("Accept", "application/json");
            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            req.setRequestHeader("OData-MaxVersion", "4.0");
            req.setRequestHeader("OData-Version", "4.0");
            req.onreadystatechange = function () {
                if (this.readyState == 4 /* complete */) {
                    req.onreadystatechange = null;
                    if (this.status == 200) {
                        var accounts = JSON.parse(this.response).value;
                        renderAccounts(accounts, token);
                    }
                    else {
                        var error = JSON.parse(this.response).error;
                        console.log(error.message);
                        errorMessage.textContent = error.message;
                    }
                }
            };
            req.send();
        }

        function UpdateAccount(params, token) {    
            // Handle ADAL Errors.
            if (error || !token) {
                errorMessage.textContent = 'ADAL error occurred: ' + error;
                return;
            }
            var req = new XMLHttpRequest();
            req.open("PATCH", encodeURI(organizationURI + "/api/data/v9.1/accounts(" + params.accountid + ")"), false);
            req.setRequestHeader("Authorization", "Bearer " + token);
            req.setRequestHeader("Accept", "application/json");
            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            req.setRequestHeader("OData-MaxVersion", "4.0");
            req.setRequestHeader("OData-Version", "4.0");
            var body = JSON.stringify({
                "name": params.name,
                "address1_city": params.city
            });
            req.send(body);
            if (req.readyState === 4) {
                if (req.status === 204) {
                    var uri = req.getResponseHeader("OData-EntityId");
                    var regExp = /\(([^)]+)\)/;
                    var matches = regExp.exec(uri);
                    var accountid = matches[1];
                    alert(params.name + " Updated");
                }
                else {
                    var error = JSON.parse(req.response).error;
                    alert(error.message);
                }
            }
        }

        function AddAccount(params, token) {
            // Handle ADAL Errors.
            if (error || !token) {
                errorMessage.textContent = 'ADAL error occurred: ' + error;
                return;
            }
            var account = {};
            account["name"] = params.name;
            account["address1_city"] = params.city;
            var req = new XMLHttpRequest();
            req.open("POST", encodeURI(organizationURI + "/api/data/v9.1/accounts"), false);
            req.setRequestHeader("Authorization", "Bearer " + token);
            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(JSON.stringify(account));
            if (req.readyState === 4) {
                if (req.status === 204) {
                    var uri = req.getResponseHeader("OData-EntityId");
                    var regExp = /\(([^)]+)\)/;
                    var matches = regExp.exec(uri);
                    var accountid = matches[1];
                    alert(params.name + " Created");
                    return accountid;
                }
                else {
                    var error = JSON.parse(req.response).error;
                    alert(error.message);
                }
            }
        }

        function DeleteAccount(params, token) {
            // Handle ADAL Errors.
            if (error || !token) {
                errorMessage.textContent = 'ADAL error occurred: ' + error;
                return;
            }
            var req = new XMLHttpRequest();
            req.open("DELETE", encodeURI(organizationURI + "/api/data/v9.1/accounts(" + params.accountid + ")"), false);
            req.setRequestHeader("Authorization", "Bearer " + token);
            req.setRequestHeader("Accept", "application/json");
            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            req.setRequestHeader("OData-MaxVersion", "4.0");
            req.setRequestHeader("OData-Version", "4.0");
            req.send();
            if (req.readyState === 4) {
                if (req.status === 204) {
                    alert(params.name + " Deleted");
                }
                else {
                    var error = JSON.parse(req.response).error;
                    alert(error.message);
                }
            }
        }

        function commonError(data) {
            return "Error Occured during Operation. Please try again";
        }

    </script>
    <style>
        body {
            font-family: 'Segoe UI';
        }

        table {
            border-collapse: collapse;
        }

        td, th {
            border: 1px solid black;
        }

        #errorMessage {
            color: red;
        }

        #message {
            color: green;
        }
    </style>
</head>
<body>
    <button id="login">Login</button>
    <button id="logout" style="display:none;">Logout</button>
    <button id="getAccounts" style="display:none;">Get Accounts</button>
    <div id="errorMessage"></div>
    <div id="message"></div>   
    <table id="grid"></table>
    <div id="pager2"></div>
 </body>
</html>

%d bloggers like this: