Thursday, February 4, 2016

Keypress methods in CRM2016

CRM2016 introduced the new keypress methods for text and numeric fields to support keypress events on CRM forms. These methods will be useful to provide immediate feedback on key press. Traditionally, all the validations and actions were executed via the “on Change” event. These methods include
  • addOnKeyPress
Use this method to attach an event handler to the keypress event
  • removeOnKeyPress
Use this method to remove an event handler to the keypress event
  • removeOnKeyPress
Use this method to manually fire an event handler to the keypress event
For this blog, I have created sample code that will stop the input of numbers in the name field of the account record.
Here are the steps
  1. Create a new JScript web resource and add the following code to it.

     // JavaScript source code  
     function keyPress()  
     {  
       //attach the validateInput function to the keypress event of the name attribute  
       Xrm.Page.getControl("name").addOnKeyPress(validateInput);    
     }  
     function validateInput() {  
       //get the value of the name field  
       var input = Xrm.Page.getControl("name").getValue();  
       if (input != "") {  
         //check if the last key pressed is a number  
         if (isNaN(input.substr(input.length - 1)) == false) {  
           //display the message  
           alert("Numeric values are not allowed in the account name");  
         }  
       }  
     }  
    

  2. Save and publish the web resource.
  3. Open the account form in customization mode.
  4. Add the JScript web resource to the form and call the keypress() method from load.
  5. Save and publish the account form.
  6. Test the code. If you try to press a number key on the name field you will get an error message as shown in the following screenshot.


Sunday, January 31, 2016

CRM Web API and CORS Support

With the introduction of WEB APIs in CRM2016, you can do all the things that you used to do using organization services (SOAP endpoints). It is good news but the greatest news for me is the addition of CORS support.


Remember the days when you could not use CRM REST endpoints for standalone applications because of CORS, now you can. According to the SDK, the new WEB API supports cross-origin web resource request when called using OAuth token authentication.This means that we can now create standalone and mobile applications using WEB API. The SDK contains a sample page to demonstrate this functionality. In this blog, I will follow that sample with some additional screenshots.


Here is the step by step guide to create a html page using CRM Web API. I am using CRM Online for this post.

Signup up CRM2016 online

Setup a 30 day free trial CRM2016 organization from the following link:

Creating the web application

  1. Using Visual Studio 2015, create a new ASP.Net web application project.
  2. Choose the “Empty” template.
  3. Add a new HTML page to the project and name it “CreateAccounts”. Copy the following code and paste it into the HTML page.

     <!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://hpeaustralia.crm6.dynamics.com"; //The URL to connect to CRM Online  
      var tenant = "hpeaustralia.onmicrosoft.com"; //The name of the Azure AD organization you use  
      var clientId = "ef9166ae-8d3f-48c9-b260-243d29f15355"; //The ClientId you got when you registered the application  
      var pageUrl = "http://localhost:39812/CRMAccounts.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>  
    
  4. The highlighted part in the above code are the variables that needs to be set to make this code work properly. I have left my settings for those variables in the code. Please change the values of these variables to match your system.
  5. Run the code. It will open a new browser window. Check the URL of that page. It will look something like http://localhost:3764/CrerateAccounts.html
  6. Replace the value of the variable “pageUrl” with the your URL from step 5 above.
Note:  The next heading “Register the application with windows Azure” will provide the value for the “clientId” variable of the code.

Register the application with windows Azure

  1. If you don’t have a Windows Azure account then you can create a trial account attached to CRM Online domain by logging into Office 365. Go to step 10.
  2. If you already have a Windows Azure subscription then you need to associate your Office 365 subscription (CRM online account) to the Windows Azure subscription. I already have an Window Azure subscription.
  3. Logon to Azure portal account.
  4. Click on “Active Directory” as shown in the following screenshot and click “New” to associate your Office 365 domain to Windows Azure.
  5. Select “Custom Create” from the following screen
  6. Select “Use existing directory” and tick “I am ready to be signed out”.
  7. Login as the admin of your Office 365 (CRM Online) account. You will see the following message.
  8. Click “Sign out now” on the following screen
  9. Login to the Windows Azure portal again using your Windows Azure account. You will now see 2 active directories.
  10. Click on the CRM directory, It will display the following screen.
  11. Click on the "Applications" tab and select add, as highlighted in the following screenshot.
  12. Select “Add an application my organization is developing”.


  13. Enter the following information:
    • Sign-on URL
      This is the URL which the user should be redirected to after they sign in. For debugging purposes in Visual Studio it should be http://localhost:####/CRMAccounts.html where #### represents the port number you got from step 4 of the Create a web application project procedure.  These are the same values as step 5 of the “Creating the web application”  section of the blog.
    • APP ID URI
      This must be a unique identifier for the application. Use https://XXXX.onmicrosoft.com/CRMAccounts . Where  XXXX is the Active Directory tenant.
  14. With the tab of the newly registered app selected, click "Configure" and locate the Client id. Copy the id and update the “clientId”  variable  of the web application.
  15. Select “Add application” and choose “Dynamics CRM Online”.
  16. Under permissions to other applications, you will find a row for "Dynamics CRM Online" and "Delegated Permissions: 0". Select this and add "Access CRM Online as organization users".
  17. Save the application registration.
  18. Click on “Manage Manifest” and select “Download Manifest”.
  19. Manifest is a json file. Open the file and locate the line: "oauth2AllowImplicitFlow": false, and change false to true and save the file.
  20. Upload the manifest file.


Run the web application

  1. Now go back to your web application and press F5 to run the page. It will open the page in the browser.
  2. Click on login. The system will take you to the login page. The page will display the name of the logged in user.
  3. Click on “Get Accounts”. The browser will display the following page.

That is it. Happy coding..

Sunday, January 24, 2016

How to fix the date format in CRM Notes

A few months ago, one of our customers reported that CRM was displaying an incorrectly formatted date on the notes. The issue was that the “Created On/ Modified On” date on notes was showing American date format (mm/dd/yyyy).
 
The CRM "System Settings" is configured to use “Australian English” format and so does the user options including the time zone. We are working with CRM2013 (on-premise).
 
The following screen shot is displaying the record and a note attached to that record. These records were created on the same date.
 
The “Created On” date is displaying the correct date 12th of March 2015 but the notes are showing “Thursday, 3 December 2015”.
 
I don’t know the reason behind this problem but I found a solution on this forum.
 

Solution

  1. Logon to the CRM server. Open the IIS Manager.
  2. Navigate to “Microsoft Dynamics CRM” site and click on “.Net Globalization”. IIS Manager will display the following screen.

  3. Change the culture value to “English (United States)”

  4. Apply the change and restart the website.
  5. Open the record and check the dates on the Notes. It should display the right date now.

Monday, December 21, 2015

CRM OData (REST) queries and special characters

In this blog, we will discuss "How to handle special characters in CRM OData queries". Every now an then we have to query the data based on the fields other than entity Ids. Most of the time OData queries works as expected except if the filtering parameter conatins special characters. OData queries does not support special characters as a filter parameters.

For example, if you are searching for a customer with an apostrophe in the  name (“Simon O’ Donnel”),  the OData query will throw a following error message.












If you try to search for a customers with special characters in the email address (abc#123@test.com) , we  encountered the following error message.











The reason is that these special characters has different meaning when used in URLs. The JavaScript “encodeUri” or  “encodeUriComponent” does not solve this problem. Here is the list of the special characters that needs to be replaced when used in the OData queries.
https://msdn.microsoft.com/en-us/library/aa226544(SQL.80).aspx

Special character Special meaning Hexadecimal value
+ Indicates a space (spaces cannot be used in a URL). %2B
/ Separates directories and subdirectories. %2F
? Separates the actual URL and the parameters. %3F
% Specifies special characters. %25
# Indicates bookmarks. %23
& Separator between parameters specified in the URL. %26

The apostrophe is not mentioned in the table. The apostrophe needs to be replaced with double apostrophes.
Now you can write a separate function to replace these characters with the appropriate hexadecimal value.

Note: Do not use the “JavaScript String replace() Method”. It will replace the first occurrence of the special characters. if you  have 2 occurence of the same special characters in the filtering parameter, it will fail. So use the regular expression to replace the characters.

You can create a  separate function and call it for all the filtering parameter before you pass it to the query.

function replaceSpecialCharacters(attribute) {
  // replace the single quotes
     attribute = attribute.replace(/'/g, "''");

     attribute = attribute.replace(/"+"/g, "%2B");
     attribute = attribute.replace(/\//g, "%2F");
     attribute = attribute.replace(/"?"/g, "%3F");
     attribute = attribute.replace(/%/g, "%25");
     attribute = attribute.replace(/#/g, "%23");
     attribute = attribute.replace(/&/g, "%26");
     return attribute;
}


Happy Coding…

Friday, October 30, 2015

CRM SOAP Library- Part 3 (Testing CRM web resources for CRM Online in Visual Studio)

This is a part 3 of the CRM Soap Library series. This blog covers how to test the web resources that make CRM web services calls  from visual studio for MSCRM Online.

If you run the CRM soap library sample or "StartUp.htm" page from my last blog CRM SOAP Library - Part 2 (Project Structure) , you will get the following  error.

“Sdk.Util.getClientUrl Unable to get clientUrl. Context not available.”

This is a straight forward error. The library is trying to get the CRM URL from global context or Xrm.page.Context. For development purposes,  you can replace the “GetGlobalContext().getClientUrl()” line in “Sdk.Soap.min.js” with your  CRM Online URL.


Now if you try to run the code after making the change,  code will throw the following error.

“status: 401: Unauthorized”

It becomes a pain when you have to keep deploying Java Script resources to CRM to test them. There are hundreds of forums/blogs that talk about this problem but you can’t not see any solution.

I figured out a way around this problem with the help of “Fiddler”.So, here is hack that will allow you to run/test you web resources without deploying them in CRM.

Here is the step by step tutorial to achieve this.
  1. If you don't have fiddler installed already, install it.you can download it from http://www.telerik.com/download/fiddler.
  2. Start the fiddler and make sure “Capture Traffic” is selected  in the “File” menu as shown in the screen shot below.
     image
  3. Logon to your CRM organisation. I am using CRM Online for this tutorial.
  4. Switch to fiddler and double click on  a CRM URL from the session pane as shown in the screen shot.
    image
  5. In the second pane, select “Inspectors>>Cookies” as shown in the screen shot below. if the contents of cookies for the selected request does not look the same try some other URL from the session list.
    image
  6. Look for “MSISAuth” in the contents and select everything from that text onwards and paste it notepad.
  7. Select “Tools>>Customize Rules” as shown in the screen shot below. It will open the “CustomRules.js” file.
    image
  8. Search for  “OnBeforeRequest(oSession: Session) function in the file and add the following code to it.

    1:  if (oSession.PathAndQuery=="/XRMServices/2011/Organization.svc/web")  
    2:   {  
    3:               //appending the cookie data for the request  
    4:            oSession.oRequest["Cookie"] = (oSession.oRequest["Cookie"] + "; text copied in step 6" );  
    5:  }  
    
    

  9. Replace the highlighted text with the text copied in step 6. Save the changes to the file.
  10. Open up your HTML page in VS and test it. You won’t get the unauthorised error  anymore.

Thursday, October 22, 2015

CRM SOAP Library - Part 2 (Project Structure)

This is the second part of my blog www.mscrmshop.blogspot.com.au/2015/10/crm-soap-library-sdksoapjs-part-1.html. In this blog I will discuss the Visual Studio project structure for JavaScript(SOAP endpoints) projects. The sample project provided by Microsoft has the following structure.

image

All the code is contained in the folder '_samples'. There are 3 sub folders in that folder.
  • min:
    This folder contains the minified version of Sdk.soap.min.js, jquery_1.9.1.min.js and folders for actions, entities and messages.
  • sampleCode:
    This is working folder where developers will write their html and JavaScript  web resources. This folders contains 3 subfolders to organise the images, pages(html), and scripts.
  • vsdoc:This folder contains all the same files and folders as the 'min' folder but they are not min-ified. Libraries in this folder contains comments etc. for the developer. Script files from this folder will be used in sampleCode scripts to provide IntelliSense.

Project Template

I think development teams should use project templates if they are doing similar work all the time. It brings consistency onto the project structure. I have changed a few things around in the sample project and turned it into a project template. My project structure looks like the following screen shot.

 image

I got rid of the '_sample' folder. I have renamed the 'min' folder to 'libs' as this folder also contains the SOAP library as well as the jquery library. I have renamed 'sampleCode' to 'webresources' and left the vsdoc as it is. I have deleted most of the sample files from this solution as I want to use this project as a project template. I have kept a few files from the sample solution to use as templates if required.

You can download my project template from: Project Template.

Now when developers will starts a webresource project using the soap endpoint. They will select a project type of “CRM SOAP JavaScript” project as shown in the following screen shot.

image

By doing that you  have same folder structure for all webresource projects using SOAP endpoints.

The following screen shot displays the structure of the new project created using the template.

image

Working with the files

  1. libs folder
    The following screen shot displays all the files and sub folders in the libs folder. The most important thing to remember is to use the min-ified version of all the JavaScript files to reduce the size. 
    image

    • the root folder contains the Sdk.soap.min.js and jquery_1.9.1.min.js files

    • the 'actions' folder contains all the custom action classes. The custom action will be created using Sdk.Soap.js Action Message Generator.

    • the 'entities' folder contains all the CRM entity classes. These classes will be used for early binding.

    • the 'message' folder contains all the other messages supported by the library. The library supports 202 different messages. You can add and remove the messages required by your project.

  2. vsdocs folder
    This folder contains all the files and folders as the 'libs' folder. The only difference is that the JavaScript files in this folders are not min-ified. These files will be used just for IntelliSense and won’t be uploaded into CRM.

  3. webresources folder
    This is the real working folder. This folder contains the following files and folders:
    image

    • the 'images' folder contains all the images used in the HTML web resources.

    • the 'pages' folder contains all the HTML websesources

    • the 'scripts' folder contains all the JavaScript files that will be called by the html webresources/CRM forms.

      I have added a StartUp.htm and StartUp.js to the project template as starting webresources. You can modify them for your project or use as reference.
      The following section displays the source code for StartUp.htm

      1:  <html>  
      2:  <head>  
      3:   <title>StartUp Page</title>  
      4:   <script src="../../../ClientGlobalContext.js.aspx" type="text/javascript"></script>  
      5:   <script src="../../libs/Sdk.Soap.min.js"></script>  
      6:   <script src="../../libs/jquery_1.9.1.min.js"></script>  
      7:   <script src="../../libs/entities/Sdk.Account.min.js"></script>  
      8:   <script src="../scripts/StartUp.js"></script>  
      9:   <!--<script src="../../libs/messages/Sdk.WhoAmI.min.js"></script>   
      10:   <script src="../../libs/actions/Sdk.sample_SimpleAction.min.js"></script>-->  
      11:   <script type="text/javascript">  
      12:   "use strict";  
      13:   document.onreadystatechange = function () {  
      14:    if (document.readyState == "complete") {  
      15:    }  
      16:   }  
      17:   function clearMessages() {  
      18:    document.getElementById("messages").innerHTML = "";  
      19:   }  
      20:   function earlyBindingSample() {  
      21:    clearMessages();  
      22:    writeToPage("Starting 'Early Binding' Sample");  
      23:    try {  
      24:    startEarlyBindingSample();  
      25:    }  
      26:    catch (e) {  
      27:    writeToPage(e.message);  
      28:    }  
      29:   }  
      30:   </script>  
      31:   <style type="text/css">  
      32:   body  
      33:   {  
      34:    font-family: "Segoe UI";  
      35:   }  
      36:   </style>  
      37:  </head>  
      38:  <body>  
      39:   <button onclick="earlyBindingSample()">&quot;Early Binding&quot; Sample</button>  
      40:   <ol id="messages" />  
      41:  </body>  
      42:  </html>  
      

      The script section highlighted in yellow lists all the JavaScript files required for this webresource. You can add the reference to your custom actions, entities and messages as required.
      • ClientGlobalContext.js.aspx:
        This file will get the context for the webresource

      • scripts/Sdk.Startup.js:
        This file contains the startEarlyBindingSample() function that the StartUp.htm webresource will call.

      The following code displays the reference directive from the StartUp.js. 

      1:  /// <reference path="../../vsdoc/Sdk.Soap.vsdoc.js" />  
      2:  /// <reference path="../../vsdoc/entities/Sdk.Account.vsdoc.js" />  
      3:  /// <reference path="../../vsdoc/jquery_1.9.1_vsdoc.js" />  
      
      These directives are used to provide IntelliSense. You can read the following article to get detail information on JavaScript IntelliSense. https://msdn.microsoft.com/en-us/library/bb385682.aspx  As you can see the code above references “Sdk.Account.vsdoc.js”. It will add the IntelliSence for the account entity as shown in the screen shot below.

      image
    That is all about the project structure. I hope this will give you enough information on how to setup a project structure for the Sdk.soap.js library.

    Another feature that would be nice, would be a one click deployment into CRM...

Monday, October 19, 2015

CRM SOAP Library – sdk.soap.js Part 1

This blog post is related to the CRM soap library created by the CRM SDK team last year. This library helps with writing JavaScript for web resources using SOAP endpoints just like C# code.  I am surprised that it only has 2600 downloads. I believe more people should use it. It provides a lot of functionality and will help to reduce code duplication in a project.
The library includes 2 files:
  • Sdk.Soap.min.js This is the minified version of the library. The size of the file is around 164kb.
  • Sdk.Soap.vsdoc.jsThis file should be used at design time to add IntelliSense to JavaScript

Advantages/Benefits

The following lists some of the benefits/advantages of using this library.
  1. Writing JavaScript like C#
    The library helps you to write JavaScript like C# code. It provides object models, methods and messages like C#. It is more productive if you are a C# developer.

  2. IntelliSense
    The Sdk.Soap.vsdoc.js file contains comments for the developers. It will be used at design time to provide IntelliSense. You just need to add a reference directive on the top of your .js file as shown below:
    /// <reference path="..path/Sdk.Soap.vsdoc.js" />

  3. Choice of Early Bound and Late Bound Classes
    The library provides the option to chose early binding and late binding in your code. I prefer the late binding but other people may prefer early binding classes as it provides the IntelliSense at design time for CRM entities. The solution also provides an early binding class entities generator to generate early bind classes for CRM entities. It is an equivalent of  crmserviceutil.exe

  4. Choice of Namespaces
    The library supports the following 8 core IOrganisationService methods.
    Associate,Create, Delete, Disassociate, Execute, Retrieve, RetrieveMultiple and Update.

    The library provides the 4 different namespaces that implement these core methods:


    • Sdk.Async:  It executes the methods asynchronously. The method signatures provide the  successCallBack and errorCallBack parameters.
    • Sdk.Sync:  It executes the methods synchronously.
    • Sdk.jQ:  It is an alternative approach to implementing asynchronous operations. It returns a jQuery.Deferred object/Promise. The initial state of the object is pending. The code will wait until the promise is resolved or rejected to execute the next line of the code.  In short, it is like writing synchronous code for asynchronous calls. I will post some sample code to explain the difference between callbacks and promises at a later date.

      This namespace depends on the existence of the jQuery.
                 
    • Sdk.Q:This is also the implementation of the “Promise” concept discussed above in Sdk.JQ.

  5. Messages/Actions
    Apart from the 8 core methods, the library supports 202 different methods. The library also provides a utility to create methods for custom action methods.

  6. Supported Queries
    The Sdk.Soap.js library supports the three main query styles used with retrieve operations:

Things to consider

  1. The library was originally written for CRM2013. The Sdk.Xml.getEnvelopeHeader function specifies an SdkClientVersion value of 6.0. It does work for CRM2013 and CRM2015. It may change in future.
  2. It does not contain all the messages.Please check the documentation on the libarary page.
  3. Delete the messages that are not required for your project to reduce the size of the JavaScript file.
  4. Delete the namespaces that are not required
Downloads
    Here is the list of the downloads for the library:
  1. Sdk.Soap.js (contains the core libraries)

  2. Sdk.Soap.js Entity Class Generator (tool to create libraries for CRM entities for ‘early binding’ and IntelliSense)

  3. Sdk.Soap.js Action Message Generator (tool to generate the support libraries for custom actions in your organization.
  4. Sdk.Soap.js Samples (code sample using the library)