Basic but needed – In this blog post i will break down the CRM rest builder query code line by line to help you understand what exactly happening in the piece of code.
This post is basically for the the people who are getting started with Dynamics 365 and also for those who did not care too much about what happening inside the code as long as it serve their purpose of retrieve/update/create etc.
Let’s get started. So I have generated a simple piece of code for retrieve request
var req = new XMLHttpRequest();
req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/accounts(475b158c-541c-e511-80d3-3863bb347ba8)", 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 result = JSON.parse(this.response);
var accountid = result["accountid"];
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send();
XMLHttpRequest
(XHR) objects are used to interact with servers. Here we are interacting Dynamics 365 servers.
1. XMLHttpRequest
// Here we first create object of XMLHttpRequest
var req = new XMLHttpRequest();
2. Syntax : XMLHttpRequest.open(method, url,async)
XMLHttpRequest
methodopen()
initializes a newly-created request GET - is a http reqeust method used to get data url - the URL to send the request to the server So here we are sending request to service root url [org name + /api/data/v9.1/] Example https://azuredevfordev.crm8.dynamics.com/api/data/v9.1/ You can find the service root URL in developer resources aync- optional Boolean parameter, defaulting totrue
, indicating whether or not to perform the operation asynchronously. If not provide or set to true -> Code executes synchronously otherwise code will execute asynchronously
/* So here method is GET,
url is
https://azuredevfordev.crm8.dynamics.com/api/data/v9.1/
async - is true i.e synchronous
*/
req.open("GET", Xrm.Page.context.getClientUrl() +
"/api/data/v9.1/accounts(475b158c-541c-e511-80d3-3863bb347ba8)", true);
req.setRequestHeader
Okay got it so far but what’s happening here in req.setRequestHeader , I see a bunch of them
Here we are setting the HTTP request headers. But what are HTTP headers actually?
HTTP headers let the client and the server pass additional information with an HTTP request or response. An HTTP header consists of its case-insensitive name followed by a colon (:
), then by its value.
Syntax
XMLHttpRequest.setRequestHeader(header, value)
header - name of HTTP header
value - value of HTTP header
setRequestHeader()
sets the value of an HTTP request header. When using setRequestHeader()
, you must call it after calling open()
, but before calling send()
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
OData-MaxVersion – Clients SHOULD specify an OData-MaxVersion request header. If specified the service MUST generate a response with an OData-Version less than or equal to the specified OData-MaxVersion.
Header value states the maximum version of the protocol the client can accept in a response.
OData-Version
-to specify the exact data service version. If both headers are present, precedence is given to OData-MaxVersion
.
3. Content Negotiation – Now we will talk about Content Negotiation
req.setRequestHeader("Accept", "application/json");
Generally, resources can have multiple presentations, mostly because there may be multiple different clients expecting different representations. Asking for a suitable presentation by a client, is referred as content negotiation.
“Accept”, “application/json” –
Syntax – Accept: <MIME_type>/<MIME_subtype>
application – Any kind of binary data that doesn’t fall explicitly into one of the other types
json – mime_subtype which specifies that client is excepting response in json format.
You can specify the other format like html,xml, etc
To determine what type of representation is desired at client side, HTTP header ACCEPT
is used. For example here ,it simply means client is requesting data in Json format.
req.setRequestHeader("Accept", "application/json");
4. “Content-Type”, “application/json; charset=utf-8”
So Content-Type and Accept seems to be doing the same thing. Is it so? No, let see how they are different Accept: is what client is expecting. Content-Type: is what format the actual data is in it's primarily meant for put or post request However, strictly speaking the specs itself does not rule out the possibility of HTTP GET contains a payload https://tools.ietf.org/html/rfc7231#section-4.3.1 Content - type is Representation header field which provide metadata about the representation. When a message includes a payload body, the representation header fields describe how to interpret the representation data enclosed in the payload body
Also what does charset=utf-8
doing here?
Content-type: application/json; charset=utf-8
designates the content to be in JSON format, encoded in the UTF-8 character encoding.
5. “Prefer”, “odata.include-annotations=\”*\””
The Prefer request header field is used to indicate that particular server behaviors are preferred by the client but are not required for successful completion of the request
What does odata.include-annotations=\”*\”” is doing here?
“*” – represent all annotations
What happens when you retrieve a lookup field? You get a bunch of other values along with Guid
This is because we have include all annotations in the code. Now try with “-*”. You will get only Guid. This is because “-*” indicates no annotation.
Example of annotations
6. this.readyState
While we debug we get multiple values for this.readyState like 0,1,2,3,4 but have we tried to figure out what they actually represent?
this.readyState – property returns the state an XMLHttpRequest client is in
When it’s 4 state is DONE.
7. req.onreadystatechange
property defines a function to be executed when the readyState changes.
XMLHttpRequest.onreadystatechange = callback; callback
is the function to be executed when the readyState
changes.
8. this.state
HTTP response status codes indicate whether a specific HTTP request has been successfully completed.
9. this.response
response
property returns the response’s body content as an ArrayBuffer
, Blob
, Document
, JSON, or DOMString
10. req.send()
send()
sends the request to the server. If the request is asynchronous (which is the default), this method returns as soon as the request is sent.
If the request is synchronous, this method doesn’t return until the response has arrived.
send()
accepts an optional parameter which lets you specify the request’s body; this is primarily used for requests such as PUT
.
References