Export (0) Print
Expand All

Use the OData endpoint with Ajax and JScript web resources

Applies To: Microsoft Dynamics CRM 2013, Microsoft Dynamics CRM Online

The OData endpoint lets you interact with Microsoft Dynamics CRM 2013 and Microsoft Dynamics CRM Online data by using JavaScript libraries. You create script web resources using files defining the JavaScript libraries. Then you associate functions in the libraries with form or field event handlers or ribbon command actions. You can use them as you would any other JavaScript library within webpage (HTML) web resources.

Ajax

AJAX (Asynchronous JavaScript and XML) is a web development technique used to create interactive web applications. Server requests are made from the browser in the background using an XmlHttpRequest object. Although you can send synchronous requests, the recommended practice is to send asynchronous requests. Asynchronous requests require two JScript functions, one to send the request and a second “callback” function to process a response.

The JavaScript Object Notation (JSON) format is used for serializing and transmitting structured data much in the same way that XML is typically used. Like XML, it’is text based and designed to be readable by humans. To convert regular JavaScript objects into the JSON format you use the JSON.stringify method. Because the text in JSON defines JavaScript objects, the text could be converted to JavaScript objects by using the eval method. However, this practice creates security vulnerabilities. You should use the JSON.parse method instead.

XmlHttpRequest (sometimes referred to as XHR) provides capabilities to configure and send requests and define a callback function if the request is asynchronous. The HTTP response from the server includes a status code indicating whether the request was successful. HTTP status code values in the 200 range are considered successful.

An XmlHttpRequest provides instructions to the server about the format of any data to be included in the response. Because the ODATA endpoint supports both ATOM and JSON formats, you have the option to request data to be returned in the XMLATOM format. However, with JavaScript code the expected typical request will use JSON because it’s easily consumable using JavaScript.

Method tunneling through POST

The OData protocol uses less common HTTP verbs PUT and DELETE as well as defining a new verb: MERGE. Depending on the supporting libraries you use, you may encounter issues while using these verbs. The way to work around this is to use the POST verb and specify an X-HTTP-MethodHTTP header with the desired action. Use the setRequestHeader method to override the action specified in the XmlHttpRequest.

Access the server URL

The first thing to do when you start to use the ODATA endpoint with JavaScript is establish the URL to the organization root URL. Use the getClientUrl function from the context object.

Use XMLHttpRequest

jQuery is a great library with a variety of uses, but using jQuery is not a prerequisite for performing operations using the ODATA endpoint for Microsoft Dynamics CRM. We recommend you don’t use jQuery in form scripts or command scripts that run in application pages but use the XmlHttpRequest directly and avoid having to load the jQuery library. jQuery$.ajax uses the XmlHttpRequest available in the browser. Using this object directly is slightly different from using $.ajax. If you’re already familiar with using XMLHttpRequest you should continue to use it. If you have always used jQuery, consider using XMLHttpRequest directly. More information: XMLHttpRequest Object

With XmlHttpRequest, you create an event handler for the onreadystatechange event and detect when the request has completed. In the event handler, check the status code returned to determine whether the request succeeded. Finally, use the open and send methods. The following sample uses XmlHttpRequest to create a new account record.

var account = {};
    account.Name = "Sample Account";
    var jsonAccount = JSON.stringify(account);

    var createAccountReq = new XMLHttpRequest();
    createAccountReq.open("POST", Xrm.Page.context.getClientUrl() + "/XRMServices/2011/OrganizationData.svc/AccountSet", true);
    createAccountReq.setRequestHeader("Accept", "application/json");
    createAccountReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    createAccountReq.onreadystatechange = function () {
        createAccountReqCallBack(this);
    };
    createAccountReq.send(jsonAccount);

function createAccountReqCallBack(createAccountReq) {
    if (createAccountReq.readyState == 4 /* complete */) {
        createAccountReq.onreadystatechange = null; //avoids memory leaks
        if (createAccountReq.status == 201) {
            //Success
            var newAccount = JSON.parse(createAccountReq.responseText).d;
        }
        else {
            //Failure
            errorHandler(createAccountReq);
        }
    }
};

For more examples using XMLHttpRequest, see Sample: Create, retrieve, update, and delete using the OData endpoint with JavaScript

Use jQuery

jQuery is a popular JavaScript library that is included with web application projects in Microsoft Visual Studio. jQuery provides an extensive framework of objects and functions that let you query and work with HTML pages using JavaScript. To use XMLHttpRequest, jQuery provides the jQuery.ajax method.

noteNote
We don’t recommend using jQuery with form scripts or commands. More information: Use of jQuery.

The jQuery object is referenced using the $ character so the short form for jQuery.ajax is $.ajax. The ajax method is typically used with an imperative syntax and the request is sent as soon as the object is instantiated. The following sample creates a new account record.

    var account = {};
    account.Name = "Sample Account";
    var jsonAccount = window.JSON.stringify(account);
    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        datatype: "json",
        url: Xrm.Page.context.getClientUrl() + "/XRMServices/2011/OrganizationData.svc/AccountSet",
        data: jsonAccount,
        beforeSend: function (XMLHttpRequest) {
            //Specifying this header ensures that the results will be returned as JSON.
            XMLHttpRequest.setRequestHeader("Accept", "application/json");
        },
        success: function (data, textStatus, XmlHttpRequest) {
            account = data.d;
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            errorHandler(XMLHttpRequest, textStatus, errorThrown);
        }
    });

The following table lists the properties you’ll have to know about to process HTTP requests and responses using the ODATA endpoint for Microsoft Dynamics CRM.

 

Property Name Type Comments

type

string

Use GET when you retrieve data and POST for all other operations. More information: Explicitly set the Request header to a different HTTP action

contentType

string

Specifies the type of content sent to the server. Use application/json; charset=utf-8 when you’re sending data in the JSON format.

dataType

string

The type of data expected to be returned by the server. Use json.

noteNote
Simply setting this property may be insufficient. More information: Explicitly set the Request Header to accept JSON

data

object

Set this to the value of a JSON object for create or update operations.

url

string

The ODATA endpoint URL appropriate for the action you’re performing.

beforeSend

function

A function that lets you modify the XMLHttpRequest object before it’s sent.

success

function

A callback function when a request succeeds. More information: Processing results

error

function

A function to be called if a request fails. More information: Handling errors

For more information, see Sample: Create, retrieve, update, and delete using the OData endpoint with JavaScript and jQuery.

Explicitly set the request header to accept JSON

When you’re expecting results in a JSON format, just setting the dataType property might not work. You can use the beforeSend property to explicitly set the headers on the XMLHttpRequest to return data as JSON. This is typically performed by using an anonymous function as shown in the following example.

beforeSend: function (XMLHttpRequest) {
   //Specifying this header ensures that the results will be returned as JSON.
   XMLHttpRequest.setRequestHeader("Accept", "application/json");}

When specified, any errors in XMLHttpRequest.responseText will be formatted in JSON instead of in XML.

TipTip
Even when you don’t expect any data to be returned, specifying that the results are always returned using JSON will simplify your error handling. More information: Handling errors

Explicitly set the request header to a different HTTP action

As described in POST Tunneling, when you perform an action that requires an HTTP action other than POST or GET, use POST and the beforeSend property to explicitly set the headers on the XMLHttpRequest to perform a different action. This is typically performed by using an anonymous function, as shown in the following example.

beforeSend: function (XMLHttpRequest) {
   //Specify the HTTP method DELETE to perform a delete operation.   XMLHttpRequest.setRequestHeader("X-HTTP-Method", "DELETE");
}

Handle errors

When a request isn’t successful, $.ajax will pass the following three arguments to a function set in the error property.

XMLHttpRequest
The XMLHttpRequest object.

textStatus
A string that describes the type of error that occurred. The possible values are as follows:

  • null

  • timeout

  • error

  • notmodified

  • parsererror

errorThrown
An optional exception object.

The following sample shows how to pass these arguments to a central function that manages errors.

error: function (XMLHttpRequest, textStatus, errorThrown) {
   errorHandler(XMLHttpRequest, textStatus, errorThrown);
}

The following sample shows a simple function that captures the error message and displays the result using the showMessage function.

noteNote
This function expects that any error details will be returned in JSON format. Unless the $.ajax method is configured to return results using JSON, the XMLHttpRequest.responseText would be XML.

function errorHandler(XMLHttpRequest, textStatus, errorThrown)
{ showMessage("Error : " + textStatus + ": " + JSON.parse(XMLHttpRequest.responseText).error.message.value); }

Process results

When you perform POST or GET operations you can expect that data will be returned. If you have specified that results be returned in the JSON format, the results will be in the d property of the data object returned. When you create or retrieve a record using the unique identifier, d will represent the data for the record. In every other case d will be an array.

The following sample shows processing the results of a query that returns multiple account records.

success: function (data, textStatus, XmlHttpRequest) {
   var accounts = data.d;
   for (var i in accounts) {   showMessage(accounts[i].Name);
   }}

Work with dates

There are four tasks involving dates that you may need to perform:

Parse retrieved data

When you retrieve records using the ODATA endpoint, date values are returned as strings that use the format “\/Date(<ticks>)\/” where <ticks> is the number of milliseconds since midnight January 1, 1970. For example: "\/Date(1311170400000)\/". All values returned from Microsoft Dynamics CRM represent the Coordinated Universal Time (UTC) values so no offset information is included.

There are two strategies you can use to parse dates in records returned using the ODATA endpoint:

Use a reviver function with the JSON.parse method

The JSON.parse method supports an optional reviver argument as described in the JSON.parse method documentation on MSDN. The following is an example that converts the string values that match a pattern defined in a regular expression into Date objects.

var jsontext = '{ "hiredate": "\/Date(1311170400000)\/", "birthdate": "\/Date(-158342400000)\/" }';
var dates = JSON.parse(jsontext, dateReviver);
var string = dates.hiredate.toUTCString();
// The value of string is "Wed, 20 Jul 2011 14:00:00 UTC"

function dateReviver(key, value) {
 var a;
 if (typeof value === 'string') {
  a = /Date\(([-+]?\d+)\)/.exec(value);
  if (a) {
   return new Date(parseInt(value.replace("/Date(", "").replace(")/", ""), 10));
  }
 }
 return value;
};
noteNote
This code assumes that date values will always be UTC data values and won’t include any offset information.

Use String.replace to generate a date value from a string

If you don’t use the reviver argument with the JSON.parse method, the following example shows how you can generate a Date value from a string.

var dateValue = new Date(parseInt(stringDateValue.replace("/Date(", "").replace(")/", ""), 10));

Display date values

After the string date values are converted to Date objects, you can use a variety of JavaScript methods, or create your own, to display the date as a string in a user interface. Because the JavaScript Date object is UTC aware, the dates displayed in your user interface using methods such as toString or toLocaleString will reflect the time zone settings of the user’s operating system.

However, notice that the values in your application might be different from the same values displayed in Microsoft Dynamics CRM, which doesn’t rely on the user’s operating system time zone settings. These values will be different when the user’s current operating system time zone preference doesn’t match the time zone preference saved in Microsoft Dynamics CRM. Microsoft Dynamics CRM also allows for setting personalized presentation options that won’t be applied by using standard JavaScript date functions like toString/

If you want to reconcile the displayed date and time values to match the values shown in Microsoft Dynamics CRM, you can query data stored in the UserSettings entity and entities like TimeZoneDefinition and TimeZoneRule to create functions to display dates that match the user’s preference. Microsoft Dynamics CRM doesn’t provide functions to perform these actions.

Update date values

When you change the values of a JavaScript date using standard set methods such as setMinutes or setHours, these changes are in the user’s local time. When you save the record, the actual UTC values are serialized and saved back to Microsoft Dynamics CRM. You don’t have to do anything to convert the dates to a UTC value.

When a Date is serialized, the format differs from the format that was used when the data is retrieved. As noted in Parsing Retrieved Data, dates are retrieved as strings that use the format "\/Date(1311179400000)\/". When you examine the results of JSON.stringify for date values to be passed back to the server, the format is "2013-07-20T16:30:00Z".

Set a date as criteria in a filter in a query

When you use a date value with a $filter system query option, you must use a UTC date. To convert a JavaScript Date object into the format expected for a filter, you have to process the date using a function such as the following example. The result is a string that matches the following format: datetime'2010-09-28T18:21:46:594Z' .

function getODataUTCDateFilter(date) {

 var monthString;
 var rawMonth = (date.getUTCMonth()+1).toString();
 if (rawMonth.length == 1) {
  monthString = "0" + rawMonth;
 }
 else
 { monthString = rawMonth; }

 var dateString;
 var rawDate = date.getUTCDate().toString();
 if (rawDate.length == 1) {
  dateString = "0" + rawDate;
 }
 else
 { dateString = rawDate; }


 var DateFilter = "datetime\'";
 DateFilter += date.getUTCFullYear() + "-";
 DateFilter += monthString + "-";
 DateFilter += dateString;
 DateFilter += "T" + date.getUTCHours() + ":";
 DateFilter += date.getUTCMinutes() + ":";
 DateFilter += date.getUTCSeconds() + ":";
 DateFilter += date.getUTCMilliseconds();
 DateFilter += "Z\'";
 return DateFilter;
}

See Also

Microsoft Dynamics CRM 2013 and Microsoft Dynamics CRM Online
Send comments about this topic to Microsoft.
© 2014 Microsoft Corporation. All rights reserved.
Show:
© 2014 Microsoft