Wednesday, November 19, 2014

Kendo UI Grid With CRM Data - REST Version

Like the previous SOAP version, the purpose of this example is to show how you can create your own JavaScript grid in a web resource using the Telerik Kendo UI grid control but instead in conjunction with a REST based request. Since there isn't an option to aggregate the record count on the server we'll need to deal with the total once the results come back. For this reason if you have more than a few results the REST based approach might not be best since you won't be able to page through data beyond what you've returned in your request as we are forced to page the results on the client side.

Telerik's Kendo UI grid control comes with their Professional Edition license so if this something that looks like it is useful be sure and give them some $$$. As such there is a reference to the required JS file in the sample hosted on Telerik's CDN rather than the actual file.

A few things to note:
  • Paging requires a record count so I'm getting that based on the number of records returned so paging is limited here to the records returned in the original query.
  • The row selection event is being handled to give you a start on adding more functionality to the grid. You can check out the API documentation to see all the capabilities of the grid.
  • I've renamed some of the images and references in the CSS file to remove the underscores as they aren't allowed in web resource names
  • You'll still need to upload everything to CRM as web resources

Show Me the Codez

//Remember everything needs to get uploaded to CRM as web resources to work

Xrm = window.Xrm || { __namespace: true };
Xrm.KendoUIGridREST = Xrm.KendoUIGridREST || { __namespace: true };

$(document).ready(function () {

Xrm.KendoUIGridREST.GetAccounts = function () {
    /// <summary>
    /// Executes the REST request to retrieve accounts from Dynamics CRM.
    /// </summary>
    /// <returns type="Object">JSON data consisting of results and total.</returns>

    var response = {}; = {}; = [];

    //Create the RetrieveMultiple REST request
    var req = new XMLHttpRequest();"GET", encodeURI(Xrm.Page.context.getClientUrl() +
        "/XRMServices/2011/OrganizationData.svc/AccountSet?$select=AccountId,AccountNumber,Name&" +
        "$filter=StatusCode/Value eq 1&$orderby=Name asc"), false);
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.onreadystatechange = function () {
        if (this.readyState === 4) {
            req.onreadystatechange = null;
            if (this.status === 200) {
                var returned = JSON.parse(req.responseText).d;
       = returned.results;

    return response;

Xrm.KendoUIGridREST.CreateGrid = function () {
    /// <summary>
    /// Generates the Kendo UI grid based on the retrieved accounts.
    /// </summary>

        dataSource: {
            transport: {
                read: function (options) {
                    var results = Xrm.KendoUIGridREST.GetAccounts();
            schema: {
                data: "data.results",
                total: function (results) {
            pageSize: 10
        height: 335,
        selectable: 'row',
        change: function (arg) {
            //Handle the row selection event
            $.map(, function (item) {
        columns: [
                field: "AccountId",
                hidden: true
            }, {
                field: "Name",
                title: "Name"
            }, {
                field: "AccountNumber",
                title: "Account Number"
        pageable: {
            buttonCount: 3

Xrm.KendoUIGridREST.GetContext = function () {
    /// <summary>
    /// Retrieves the CRM context information.
    /// </summary>
    /// <returns type="Object">The CRM context.</returns>

    var errorMessage = "Context is not available.";
    if (typeof GetGlobalContext != "undefined") {
        return GetGlobalContext();
    else {
        if (typeof Xrm != "undefined") {
            return Xrm.Page.context;
        } else {
            throw new Error(errorMessage);

You can download the full sample here: