{"id":2183,"date":"2016-01-05T16:42:39","date_gmt":"2016-01-05T11:12:39","guid":{"rendered":"https:\/\/www.inogic.com\/blog\/?p=2183"},"modified":"2021-12-15T16:10:29","modified_gmt":"2021-12-15T10:40:29","slug":"querying-data-in-microsoft-dynamics-crm-2016-using-web-api","status":"publish","type":"post","link":"https:\/\/www.inogic.com\/blog\/2016\/01\/querying-data-in-microsoft-dynamics-crm-2016-using-web-api\/","title":{"rendered":"Querying data in Microsoft Dynamics CRM 2016 using Web API"},"content":{"rendered":"<h2>Introduction:<strong><br \/>\n<\/strong><\/h2>\n<p style=\"text-align: justify;\">With Microsoft Dynamics CRM 2016, Web API that was in Preview for CRM 2015 is now GA. Web API is really OData V4 which is the later version of OData V2 that was implemented in earlier versions of CRM until CRM 2015.<\/p>\n<p style=\"text-align: justify;\">With CRM 2016, OData V2 is deprecated, this means that though the legacy code written using OData V2 will continue to function, it is not advised to continue to develop using this version of OData starting CRM 2016.<\/p>\n<p style=\"text-align: justify;\">The earlier version of OData was strictly restricted to CRUD operations, how with Web API you can even perform operations that earlier required us to use SOAP requests.<\/p>\n<p style=\"text-align: justify;\">In the earlier post, it was all about <a href=\"https:\/\/www.inogic.com\/blog\/2015\/12\/execute-fetchxml-using-web-api-in-dynamics-crm-2016\/\" target=\"_blank\" rel=\"noopener noreferrer\">executing FetchXML<\/a> queries using Web API, well that was to some extent because I didn&#8217;t have much success querying and applying some very common queries. After spending some more time with WEB API and trying to get things done exclusively using OData V4, I did get quite a few things figured out.<\/p>\n<p style=\"text-align: justify;\">In this post, I am listing out some of the frequently used queries and how these could be generated using Web API.<\/p>\n<h2><strong>OData v4 endpoints:<\/strong><span style=\"text-decoration: underline;\"><strong><br \/>\n<\/strong><\/span><\/h2>\n<p style=\"text-align: justify;\">Under Developer Resources, you can now find the endpoint for Web API.<\/p>\n<p><img decoding=\"async\" class=\"alignnone\" src=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2016\/01\/010516_1112_Queryingdat1.png\" alt=\"Querying data in Microsoft Dynamics CRM 2016 \" width=\"337\" height=\"84\" \/><\/p>\n<p style=\"text-align: justify;\">Notice the change in the URL structure, it is now \/api\/data\/v8.0\/<\/p>\n<p style=\"text-align: justify;\">Earlier it was \/<span style=\"color: black; font-family: Segoe UI; font-size: 10pt;\">xrmservices\/2011\/organizationdata.svc\/<br \/>\n<\/span><\/p>\n<h3><span style=\"color: black; font-family: 'Segoe UI'; font-size: 10pt;\"><strong>Sample Queries:<\/strong><\/span><span style=\"color: black; font-family: Segoe UI; font-size: 10pt; text-decoration: underline;\"><strong><br \/>\n<\/strong><\/span><\/h3>\n<ol>\n<li>\n<h4><span style=\"color: black;\">List accounts starting with A and C<\/span><\/h4>\n<p style=\"text-align: justify;\"><span style=\"color: blue; font-family: Consolas;\"><span style=\"background-color: white;\">var<span style=\"color: black;\"> qry = <span style=\"color: #a31515;\">&#8220;accounts?$filter=startswith(name,&#8217;A&#8217;) or startswith(name,&#8217;C&#8217;)&#8221;<span style=\"color: black;\">;<\/span><\/span><\/span><\/span><br \/>\n<\/span><\/p>\n<p style=\"text-align: justify;\">Since field names have not been specified all the columns are listed.<\/p>\n<p style=\"text-align: justify;\">The entitycollection does not include Set Prefix anymore besides its using the logical name throughout.<\/p>\n<\/li>\n<li>\n<h4><span style=\"color: black;\">List accounts owned by a particular user<\/span><\/h4>\n<p><span style=\"color: blue; font-family: Consolas;\"><span style=\"background-color: white;\">var<span style=\"color: black;\"> qry = <span style=\"color: #a31515;\">&#8220;<\/span><\/span><\/span>accounts?$select=name,accountnumber,_primarycontactid_value,createdon,accountcategorycode,revenue&amp;$filter=_ow<span style=\"color: #a31515;\">nerid_value%20eq%201ea6fc32-9b2d-47e6-b9ab-b5f23f69e34f<span style=\"background-color: white;\"> &#8220;<span style=\"color: black;\">;<\/span><\/span><\/span><\/span><\/p>\n<p style=\"text-align: justify;\">Here we had to provide the guid of the user that you need to filter by. Also notice that the ownerid attribute has been mentioned as _ownerid_value<\/p>\n<p style=\"text-align: justify;\">All lookups are listed in the query result to follow the naming structure<\/p>\n<p style=\"text-align: justify;\">_&lt;logicalname&gt;_value.<\/p>\n<\/li>\n<li>\n<h4>Read account details along with the primary contact phone<\/h4>\n<p style=\"text-align: justify;\">We need to use the $expand clause to request data of the related entity. However, it appears that the $expand clause only works when requesting data of a single record as shown in the below query.<\/p>\n<p><span style=\"color: blue;\"><span style=\"font-family: Consolas; background-color: white;\">var<span style=\"color: black;\"> qry = <span style=\"color: #a31515;\">&#8220;accounts(4ef2c099-bca1-e511-80de-3863bb349a78)?$select=name,accountnumber,_primarycontactid_value,createdon,accountcategorycode,revenue&amp;$filter=contains(name,'(sample)&#8217;)&amp;$orderby=name&amp;$expand=primarycontactid($select=fullname,telephone1)&#8221;<\/span><\/span><\/span><br \/>\n<\/span><\/p>\n<p style=\"text-align: justify;\">If you were to request this for the entire accounts collection, you receive the following error message<\/p>\n<pre class=\"lang:default decode:true\">{\r\n\r\n\"error\":{\r\n\r\n\"code\":\"\",\"message\":\"Expansion of navigation properties isn\\u2019t supported on entity collections.\",\"innererror\":{\r\n\r\n\"message\":\"Expansion of navigation properties isn\\u2019t supported on entity collections.\",\"type\":\"Microsoft.Crm.CrmHttpException\",\"stacktrace\":\" at<\/pre>\n<\/li>\n<li>\n<h4>List all Phone Calls of an account<\/h4>\n<p style=\"text-align: justify;\">This will display only the subject of the related phone calls.<\/p>\n<p><span style=\"color: blue; font-family: Consolas;\"><span style=\"background-color: white;\">var<span style=\"color: black;\"> qry = <span style=\"color: #a31515;\">&#8220;accounts(4ef2c099-bca1-e511-80de-3863bb349a78)?$expand=Account_Phonecalls($select=subject)&#8221;<\/span><\/span><\/span><\/span><\/li>\n<\/ol>\n<h2><strong>Understand the Query Results:<\/strong><span style=\"text-decoration: underline;\"><strong><br \/>\n<\/strong><\/span><\/h2>\n<p style=\"text-align: justify;\">Unlike the OData V2 queries, the results here are returned in JSON format<\/p>\n<pre class=\"lang:default decode:true \">{\r\n\r\n\"@odata.context\":\"https:\/\/dyn20161.crm5.dynamics.com\/api\/data\/v8.0\/$metadata#accounts(name,accountnumber,_primarycontactid_value,createdon,accountcategorycode,revenue)\",\"value\":[\r\n\r\n\"@odata.etag\":\"W\/\\\"632098\\\"\",\"name\":\"Alpine Ski House (sample)\",\"accountnumber\":\"ABCO9M32\",\"_primarycontactid_value\":\"1cf3c099-bca1-e511-80de-3863bb349a78\",\"createdon\":\"2015-12-13T17:12:15Z\",\"accountcategorycode\":null,\"revenue\":90000.0000,\"accountid\":\"4cf2c099-bca1-e511-80de-3863bb349a78\",\"_transactioncurrencyid_value\":\"5022ed92-bca1-e511-80e1-3863bb345aa8\"\r\n\r\n},{\r\n\r\n\"@odata.etag\":\"W\/\\\"632065\\\"\",\"name\":\"A. Datum Corporation (sample)\",\"accountnumber\":null,\"_primarycontactid_value\":\"1ef3c099-bca1-e511-80de-3863bb349a78\",\"createdon\":\"2015-12-13T17:12:15Z\",\"accountcategorycode\":null,\"revenue\":10000.0000,\"accountid\":\"4ef2c099-bca1-e511-80de-3863bb349a78\",\"_transactioncurrencyid_value\":\"5022ed92-bca1-e511-80e1-3863bb345aa8\"\r\n\r\n}\r\n\r\n]\r\n\r\n}<\/pre>\n<p style=\"text-align: justify;\">Now if see the results here, the primary contact id only provides the Guid, not really helpful, and for currency data types, it again returns only the number, the currency is provided as transaction guid, so again formatted value missing.<\/p>\n<p style=\"text-align: justify;\">If we want the results to return the formatted values, we need to pass the following in the header tag of the request<\/p>\n<p style=\"text-align: justify;\"><em>odata.include-annotations=&#8221;OData.Community.Display.V1.FormattedValue&#8221;<br \/>\n<\/em><\/p>\n<p style=\"text-align: justify;\">I haven&#8217;t figured it out how to pass these in the browser url, but here is the code I use to pass the header values.<\/p>\n<pre class=\"lang:default decode:true\">var qry = url;\r\n\r\nvar headers = {\r\n\r\n\r\n'Content-Type': 'application\/json',\r\n\r\nAccept: 'application\/json', 'OData-MaxVersion': 4.0,\r\n\r\nPrefer: 'odata.include-annotations=\"*\", odata.maxpagesize=3'\r\n\r\n};\r\n\r\nvar request = {\r\n\r\nrequestUri: qry,\r\n\r\nmethod: 'GET',\r\n\r\nheaders: headers,\r\n\r\ndata: null\r\n\r\n};\r\n\r\n\u00a0\r\nodatajs.oData.request(\r\n\r\nrequest,\r\n\r\nsuccessCallback,\r\n\r\nerrorCallback);<\/pre>\n<p style=\"text-align: justify;\">In the above code, you can replace the &#8220;*&#8221; with &#8220;OData.Community.Display.V1.FormattedValue&#8221;, the other preferences supported are<\/p>\n<p style=\"text-align: justify;\"><span style=\"font-family: Times New Roman;\">Microsoft.Dynamics.CRM.lookuplogicalname<br \/>\n<\/span><\/p>\n<p style=\"text-align: justify;\"><span style=\"font-family: Times New Roman;\">Microsoft.Dynamics.CRM.associatednavigationproperty<br \/>\n<\/span><\/p>\n<p style=\"text-align: justify;\">Generally, for lookups, we are used to receiving 3 set of data,<\/p>\n<p style=\"text-align: justify;\">The lookup entity name, the guid and the record name. By default we only received the Guid of a lookup field, if we need the record name and the entity name, we need to include the preferences listed above.<\/p>\n<p style=\"text-align: justify;\">If you want all preferences to be applied, pass &#8220;*&#8221;<\/p>\n<p style=\"text-align: justify;\">With all preferences the applied the result would appear as<\/p>\n<p><img decoding=\"async\" class=\"alignnone\" src=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2016\/01\/010516_1112_Queryingdat2.png\" alt=\"Querying data in CRM 2016 using Web API\" width=\"693\" height=\"246\" \/><\/p>\n<p style=\"text-align: justify;\">Lookup field details are available as shown above<\/p>\n<p style=\"text-align: justify;\">_primarycontactid_value: &#8220;1ef3c099-bca1-e511-80de-3863bb349a78&#8221;<\/p>\n<p style=\"text-align: justify;\">_primarycontactid_value@Microsoft.Dynamics.CRM.associatednavigationproperty: &#8220;primarycontactid&#8221;<\/p>\n<p style=\"text-align: justify;\">_primarycontactid_value@Microsoft.Dynamics.CRM.lookuplogicalname: &#8220;contact&#8221;<\/p>\n<p style=\"text-align: justify;\">_primarycontactid_value@OData.Community.Display.V1.FormattedValue: &#8220;Rene Valdes (sample)&#8221;<\/p>\n<p style=\"text-align: justify;\">And we now also get the revenue formatted with the currency symbol and the date.<\/p>\n<h3><strong>Paging:<\/strong><span style=\"text-decoration: underline;\"><strong><br \/>\n<\/strong><\/span><\/h3>\n<p style=\"text-align: justify;\">To handle paging you need to specify the page size, which is now called <span style=\"color: #a31515; font-family: Consolas;\"><span style=\"background-color: white;\">odata.maxpagesize=<\/span>n<span style=\"font-size: 15pt;\"><br \/>\n<\/span><\/span><\/p>\n<p style=\"text-align: justify;\">N stands for the count of records to be returned.<\/p>\n<p style=\"text-align: justify;\">You also receive the paging cookie, which will allow you to request the next set of records.<\/p>\n<p><img decoding=\"async\" class=\"alignnone\" src=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2016\/01\/010516_1112_Queryingdat3.png\" alt=\" Web API\" width=\"574\" height=\"55\" \/><\/p>\n<p style=\"text-align: justify;\">Use the nextlink url to the Web API to request the next set of data. It returns a fully qualified url with the query parameters set that can be used just as is.<\/p>\n<h3><strong>Result Count:<\/strong><span style=\"text-decoration: underline;\"><strong><br \/>\n<\/strong><\/span><\/h3>\n<p style=\"text-align: justify;\">When you include the $count=true in your query, you get the total count of the records returned by the query in the query result.<\/p>\n<p style=\"text-align: justify;\">If you query the following,<\/p>\n<p>var qry5 = &#8220;https:\/\/xxx.crm5.dynamics.com\/api\/data\/v8.0\/accounts?$count=true&amp;$top=2&#8221;<\/p>\n<p>You get<\/p>\n<p><img decoding=\"async\" class=\"alignnone\" src=\"https:\/\/www.inogic.com\/blog\/wp-content\/uploads\/2016\/01\/010516_1112_Queryingdat4.png\" alt=\"Querying data in Dynamics CRM 2016 using Web API\" width=\"542\" height=\"78\" \/><\/p>\n<p style=\"text-align: justify;\">The total count is 19 even though the results requested were only top 2<\/p>\n<p style=\"text-align: justify;\">Note, if there are more than 5000 records that the query returns, the count here would still return 5000 only.<\/p>\n<h2><strong>Conclusion:<\/strong><span style=\"text-decoration: underline;\"><strong><br \/>\n<\/strong><\/span><\/h2>\n<p style=\"text-align: justify;\">The Web API query still has a few limitations and like the earlier OData V2, there are limitations on what kind of data can be queried. You can find the complete list <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/mt628816.aspx\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>.<\/p>\n<p style=\"text-align: justify;\">In this post I have covered queries, in the later blogs hope to cover the other operations supported by WEB API.<\/p>\n<p style=\"text-align: justify;\">Make your Dynamics CRM life easy with Inogic Dynamics CRM Solutions. Read more about our add-ons <a href=\"https:\/\/www.inogic.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>.<\/p>\n<h2 style=\"text-align: left;\"><div class=\"su-heading su-heading-style-default su-heading-align-center\" id=\"\" style=\"font-size:15px;margin-bottom:5px\"><div class=\"su-heading-inner\">Cut short 90% of your manual work and repetitive data entry!<\/div><\/div><\/h2>\n<p style=\"text-align: left;\"><em>Get 1 Click apps and say goodbye to all repetitive data entry in CRM &#8211;<\/em><br \/>\n<em><strong><a href=\"https:\/\/bit.ly\/3oH7dYw\" target=\"_blank\" rel=\"noopener noreferrer\">Click2Clone<\/a> <\/strong>\u2013 Clone\/Copy Dynamics 365 CRM records in 1 Click<\/em><br \/>\n<em><strong><a href=\"https:\/\/bit.ly\/3EPjAYc\" target=\"_blank\" rel=\"noopener noreferrer\">Click2Export<\/a><\/strong> \u2013 Export Dynamics 365 CRM Report\/CRM Views\/Word\/Excel template in 1 Click<\/em><br \/>\n<em><strong><a href=\"https:\/\/bit.ly\/3EN8h2v\" target=\"_blank\" rel=\"noopener noreferrer\">Click2Undo<\/a><\/strong> \u2013 Undo &amp; Restore Dynamics 365 CRM data in 1 Click<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction: With Microsoft Dynamics CRM 2016, Web API that was in Preview for CRM 2015 is now GA. Web API is really OData V4 which is the later version of OData V2 that was implemented in earlier versions of CRM until CRM 2015. With CRM 2016, OData V2 is deprecated, this means that though the\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.inogic.com\/blog\/2016\/01\/querying-data-in-microsoft-dynamics-crm-2016-using-web-api\/\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":13,"featured_media":10692,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[16,24,65],"tags":[601,1813],"class_list":["post-2183","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dynamics-365","category-dynamics-crm-2016","category-webapi","tag-dynamics-crm-2016","tag-web-api"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/posts\/2183","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/comments?post=2183"}],"version-history":[{"count":0,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/posts\/2183\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/media\/10692"}],"wp:attachment":[{"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/media?parent=2183"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/categories?post=2183"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.inogic.com\/blog\/wp-json\/wp\/v2\/tags?post=2183"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}