Tuesday 6 February 2018

Sample code for creating a Single Page JavaScript application to Fetch Data from CRM Online using Web API

Create a web application project

  1. Using Microsoft Visual Studio 2015, create a new ASP.NET Web Application project and use the Empty template. You can name the project whatever you like.
    You should be able to use earlier versions of Microsoft Visual Studio as well, but these steps will describe using Visual Studio 2015.
  2. Add a new HTML page named SimpleSPA.html to the project and paste in the following code:
    <!DOCTYPE html>
    <html>
    <head>
     <title>Simple SPA</title>
     <meta charset="utf-8" />
     <script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.0/js/adal.min.js"></script>
     <script type="text/javascript">
      "use strict";
    
      //Set these variables to match your environment
      var organizationURI = "https:// [organization name].crm.dynamics.com"; //The URL to connect to CRM (online)
      var tenant = "[xxx.onmicrosoft.com]"; //The name of the Azure AD organization you use i.e. Active directory tenant. 
      var clientId = "[client id]"; //The applicationid you got when you registered the application
      var pageUrl = "http://localhost: [PORT #]/SimpleSPA.html"; //The URL of this page in your development environment when debugging.
    
    
      var user, authContext, message, errorMessage, loginButton, logoutButton, getAccountsButton, accountsTable, accountsTableBody;
    
      //Configuration data for AuthenticationContext
      var endpoints = {
       orgUri: organizationURI
      };
    
      window.config = {
       tenant: tenant,
       clientId: clientId,
       postLogoutRedirectUri: pageUrl,
       endpoints: endpoints,
       cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
      };
    
    
      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");
        accountsTable = document.getElementById("accountsTable");
        accountsTableBody = document.getElementById("accountsTableBody");
    
        //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();
       accountsTable.style.display = "none";
       accountsTableBody.innerHTML = "";
      }
    
    
    //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/v8.0/accounts";
       message.appendChild(retrievingAccountsMessage)
    
       // Function to perform operation is passed as a parameter to the aquireToken method
       authContext.acquireToken(organizationURI, retrieveAccounts)
    
      }
    
    
    //Function that actually retrieves the accounts
      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/v8.0/accounts?$select=name,address1_city&$top=10"), true);
       //Set Bearer token
       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);
         }
         else {
          var error = JSON.parse(this.response).error;
          console.log(error.message);
          errorMessage.textContent = error.message;
         }
        }
       };
       req.send();
      }
      //Function that writes account data to the accountsTable
      function renderAccounts(accounts) {
       accounts.forEach(function (account) {
        var name = account.name;
        var city = account.address1_city;
        var nameCell = document.createElement("td");
        nameCell.textContent = name;
        var cityCell = document.createElement("td");
        cityCell.textContent = city;
        var row = document.createElement("tr");
        row.appendChild(nameCell);
        row.appendChild(cityCell);
        accountsTableBody.appendChild(row);
       });
       accountsTable.style.display = "block";
      }
    
     </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="accountsTable" style="display:none;">
      <thead><tr><th>Name</th><th>City</th></tr></thead>
      <tbody id="accountsTableBody"></tbody>
     </table>
    </body>
    </html>
    
    
  3. Set this page as the start page for the project
  4. In the properties of the project, select Web and under Servers note the Project URL. It should be something like http://localhost:46575/. Note the port number that is generated. You will need this in the next step.
  5. Within the SimpleSPA.html page, locate the following configuration variables and set them accordingly. You will be able to set the clientId  ( applicationidafter you complete the next part of the walkthrough.
    //Set these variables to match your environment
    var organizationURI = "https://[organization name].crm.dynamics.com"; //The URL to connect to CRM (online)
    var tenant = "[xxx.onmicrosoft.com]"; //The name of the Azure AD organization you use
    var clientId = "[client id]"; //The ClientId you got when you registered the application
    var pageUrl = "http://localhost:[PORT #]/SimpleSPA.html"; //The URL of this page in your development environm

3 comments:

  1. Hi Srujan,
    Its really nice article to start with.

    Could you please explain how could we get the value for tenant parameter in Config.

    Could you please explain with a sample.

    Thanks!
    Suraj

    ReplyDelete
    Replies
    1. Hi Suraj , Thanks for reaching out. The Tenant is very specific to your organization , it should be common across all your projects. You should be able to get this from tenant admin of your organization.

      Thanks
      Srujan k

      Delete
    2. Example:- Microsoft.onmicrosoft.com

      Delete