<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[AV Explores]]></title><description><![CDATA[Devoted To Code => No Need to Code (let AI do it)]]></description><link>https://dev.ashishvishwakarma.com</link><generator>RSS for Node</generator><lastBuildDate>Sun, 17 May 2026 09:28:49 GMT</lastBuildDate><atom:link href="https://dev.ashishvishwakarma.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Power Platform Developer Tools]]></title><description><![CDATA[Fetch Xml Tester

WebApi Launcher

Power Expression Beautifier

Flow Calendar

Query Dataverse

Fetch Xml to SQL

Dataverse Row Counter

Fetch Xml Formatter]]></description><link>https://dev.ashishvishwakarma.com/power-platform-developer-tools</link><guid isPermaLink="true">https://dev.ashishvishwakarma.com/power-platform-developer-tools</guid><category><![CDATA[PowerPlatform]]></category><category><![CDATA[Dataverse]]></category><category><![CDATA[#dynamics365]]></category><category><![CDATA[xrmtoolbox]]></category><category><![CDATA[Microsoft]]></category><dc:creator><![CDATA[Ashish Vishwakarma]]></dc:creator><pubDate>Sat, 05 Jul 2025 01:06:50 GMT</pubDate><content:encoded><![CDATA[<ol>
<li><p><a target="_blank" href="https://www.ashishvishwakarma.com/FetchXmlTester/">Fetch Xml Tester</a></p>
</li>
<li><p><a target="_blank" href="https://linnzawwin.blogspot.com/p/webapi-launcher.html">WebApi Launcher</a></p>
</li>
<li><p><a target="_blank" href="https://www.ashishvishwakarma.com/PowerExpressionBeautifier/">Power Expression Beautifier</a></p>
</li>
<li><p><a target="_blank" href="https://www.ashishvishwakarma.com/FlowCalendar/">Flow Calendar</a></p>
</li>
<li><p><a target="_blank" href="https://www.ashishvishwakarma.com/qdv/">Query Dataverse</a></p>
</li>
<li><p><a target="_blank" href="https://www.ashishvishwakarma.com/FetchXMLToSQL/">Fetch Xml to SQL</a></p>
</li>
<li><p><a target="_blank" href="https://www.ashishvishwakarma.com/DataverseRowCounter/">Dataverse Row Counter</a></p>
</li>
<li><p><a target="_blank" href="https://www.ashishvishwakarma.com/FetchXmlFormatter/">Fetch Xml Formatter</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[PowerShell For Dataverse Developers]]></title><description><![CDATA[CI/CD has become an integral part of ALM these days and PowerShell is the first choice of scripting, Dataverse projects are no exception. For Setting up CI/CD for Dataverse already many extensions are available on Azure DevOps Marketplace. Here in th...]]></description><link>https://dev.ashishvishwakarma.com/powershell-for-dataverse-developers-basics</link><guid isPermaLink="true">https://dev.ashishvishwakarma.com/powershell-for-dataverse-developers-basics</guid><category><![CDATA[Powershell]]></category><category><![CDATA[PowerPlatform]]></category><category><![CDATA[powerapps]]></category><dc:creator><![CDATA[Ashish Vishwakarma]]></dc:creator><pubDate>Tue, 03 Jan 2023 18:19:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670763251068/lEtU0ohzC.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>CI/CD has become an integral part of ALM these days and PowerShell is the first choice of scripting, Dataverse projects are no exception. For Setting up CI/CD for Dataverse already many extensions are available on <a target="_blank" href="https://marketplace.visualstudio.com/azuredevops/">Azure DevOps Marketplace</a>. Here in this article, we will see how to perform different actions against Dataverse data using PowerShell which can be used further in CI/CD pipelines or other places.</p>
<h2 id="heading-install-required-modules">Install required modules</h2>
<p>We will use <a target="_blank" href="https://github.com/seanmcne/Microsoft.Xrm.Data.PowerShell">Microsoft.Xrm.Data.PowerShell</a> module created by <a target="_blank" href="https://github.com/seanmcne">Sean McNellis</a> which is a wrapper around official Microsoft modules and makes the job a lot easier.</p>
<p>You'd need to run PowerShell as admin to install a new module, then execute the below command. It would ask for confirmation before installing, enter 'Y' or 'A' to install.</p>
<pre><code class="lang-bash">Install-Module <span class="hljs-string">"Microsoft.Xrm.Data.PowerShell"</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670768034072/QcxJRKMW1.png" alt="Install-Module &quot;Microsoft.Xrm.Data.PowerShell&quot;" class="image--center mx-auto" /></p>
<h2 id="heading-making-a-connection-to-an-environment">Making a connection to an environment</h2>
<p>The Get-CrmConnection command creates a connection to the environment. If using it locally then can go for interactive mode or non-interactive mode using a connection string. We'll store the connection object to a variable $Conn.</p>
<h3 id="heading-interactive-mode">Interactive Mode</h3>
<p>Execute the below command, it would show an interactive login prompt where you can log in using your credentials and select desired organization you wish to connect.</p>
<pre><code class="lang-bash"><span class="hljs-variable">$Conn</span> = Get-CrmConnection -InteractiveMode
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670770674457/_CzNzT02L.png" alt class="image--center mx-auto" /></p>
<p>After a successful connection, you can see the contents of the $Conn object like below if you wish to.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670770485383/J2P1tvcQb.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-non-interactive-mode">Non-interactive Mode</h3>
<p>For a non-interactive connection, we need to prepare a connection string by acquiring the client id/secret from azure. Call Get-CrmConnection with the -ConnectionString parameter.</p>
<pre><code class="lang-bash"><span class="hljs-variable">$Conn</span> = Get-CrmConnection -ConnectionString <span class="hljs-string">"AuthType=ClientSecret;url=https://orgc28637dd.crm8.dynamics.com;ClientId=f8a6e260-4725-b27f-2870343ef742;ClientSecret=HLT8QoLoPYT9rzkj1rrqi.R1COGLZ.clM"</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671282286884/9SIorMWY1.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-create-new-record">Create new record</h2>
<p>New-CrmRecord is used to create new records, this accepts -EntityLogicalName &amp; Fields parameter along with -conn. This returns Guid of created record.</p>
<pre><code class="lang-bash"><span class="hljs-variable">$ContactId</span> = New-CrmRecord -conn <span class="hljs-variable">$Conn</span> -EntityLogicalName contact -Fields @{<span class="hljs-string">"firstname"</span>=<span class="hljs-string">"Ashish"</span>;<span class="hljs-string">"lastname"</span>=<span class="hljs-string">"Vishwakarma"</span>;<span class="hljs-string">"jobtitle"</span>=<span class="hljs-string">"Senior Consultant"</span>}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671374777879/M1uN8jMYH.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-retrieve-record-by-id">Retrieve record by Id</h2>
<p>To retrieve a record using Guid, Get-CrmRecord need to be called with EntityLogicalName, Id &amp; Fields to retrieve. The connection object also needs to be passed in the -conn parameter.</p>
<pre><code class="lang-bash"><span class="hljs-variable">$ContactRecord</span> = Get-CrmRecord -conn <span class="hljs-variable">$Conn</span> -EntityLogicalName contact -Id <span class="hljs-string">"9869dab8-0c7e-ed11-0000-6045bdea00fb"</span> -Fields fullname,jobtitle
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671284054765/uUOcBTgTg.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-retrieve-records-based-on-the-condition">Retrieve records based on the condition</h2>
<p>To retrieve records based on some condition Get-CrmRecords is used with -Filter* parameters. This uses fetchXml internally, record values can be accessed via the CrmRecords property.</p>
<pre><code class="lang-bash"><span class="hljs-variable">$ConsultantRecords</span> = Get-CrmRecords -conn <span class="hljs-variable">$Conn</span> -EntityLogicalName contact -Fields fullname,jobtitle -FilterAttribute jobtitle -FilterOperator eq -FilterValue <span class="hljs-string">"Consultant"</span>

<span class="hljs-variable">$ConsultantRecords</span>.CrmRecords
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671313960693/2HukGGCkc.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-query-records-using-fetchxml">Query records using fetchXml</h2>
<p>To query records with fetchXml Get-CrmRecordsByFetch is used with the -Fetch parameter which accepts fetchXml query.</p>
<pre><code class="lang-bash"><span class="hljs-variable">$FetchXml</span> = <span class="hljs-string">"&lt;fetch mapping='logical'&gt;
   &lt;entity name='account'&gt;
      &lt;attribute name='accountid'/&gt;
      &lt;attribute name='name'/&gt;
   &lt;/entity&gt;
&lt;/fetch&gt;  
"</span>

<span class="hljs-variable">$FetchXmlRecords</span> = Get-CrmRecordsByFetch -conn <span class="hljs-variable">$Conn</span> -Fetch <span class="hljs-variable">$FetchXml</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671364945265/Erb5gJYy4.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-update-records">Update records</h2>
<p>Set-CrmRecord is used to update an existing record.</p>
<pre><code class="lang-bash">Set-CrmRecord -conn <span class="hljs-variable">$Conn</span> -EntityLogicalName contact -Id 9869dab8-0c7e-ed11-81ac-6045bdea00fb -Fields @{ <span class="hljs-string">"firstname"</span> = <span class="hljs-string">"Avinash"</span> }
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671371190106/-wbNY4kL5.png" alt class="image--center mx-auto" /></p>
<p>If updating some property of already retrieved record then the below syntax can be used alternatively since it has metadata information already.</p>
<pre><code class="lang-bash"><span class="hljs-variable">$ContactRecord</span> = Get-CrmRecord -conn <span class="hljs-variable">$Conn</span> -EntityLogicalName contact -Id 9869dab8-0c7e-ed11-81ac-6045bdea00fb -Fields fullname,jobtitle
<span class="hljs-variable">$ContactRecord</span>.jobtitle = <span class="hljs-string">"Manager"</span>
Set-CrmRecord -conn <span class="hljs-variable">$Conn</span> -CrmRecord <span class="hljs-variable">$ContactRecord</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671372043450/wo1WnGEOF.png" alt class="image--center mx-auto" /></p>
<p>If you want to update a property using an already retrieved object but the property is not already present in the object, then we can first use -Add-Member to set the property and use this in Set-Record.</p>
<pre><code class="lang-bash"><span class="hljs-variable">$ContactRecord</span> | Add-Member -MemberType NoteProperty -Name lastname -Value <span class="hljs-string">"Sharma"</span>
Set-CrmRecord -conn <span class="hljs-variable">$Conn</span> -CrmRecord <span class="hljs-variable">$ContactRecord</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671372689680/B9SVqQSYn.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-delete-a-record">Delete a record</h2>
<p>Remove-CrmRecord is used to delete records. Like Set-CrmRecord this also can be used either with Id or record object. See the below examples.</p>
<pre><code class="lang-bash">Remove-CrmRecord -conn <span class="hljs-variable">$Conn</span> -EntityLogicalName contact -Id 9969ef91-e27e-ed11-81ac-002248d60670
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671378043007/HUhWB0HMO.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash">Remove-CrmRecord -conn <span class="hljs-variable">$Conn</span> -CrmRecord <span class="hljs-variable">$ContactRecord</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671378155457/tsxuFaMDa.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Retrieve Record with Simple GET In Dataverse WebAPI]]></title><description><![CDATA[Below HTTP Request retrieves all the record's fullname field from contact entity, more comma separated fields can be added
GET [Organization URI]/api/data/v9.2/contacts?$select=fullname 
Accept: application/json  
OData-MaxVersion: 4.0  
OData-Versio...]]></description><link>https://dev.ashishvishwakarma.com/retrieve-record-with-simple-get-in-dataverse-webapi</link><guid isPermaLink="true">https://dev.ashishvishwakarma.com/retrieve-record-with-simple-get-in-dataverse-webapi</guid><dc:creator><![CDATA[Ashish Vishwakarma]]></dc:creator><pubDate>Thu, 20 Jan 2022 16:59:38 GMT</pubDate><content:encoded><![CDATA[<p>Below HTTP Request retrieves all the record's fullname field from contact entity, more comma separated fields can be added</p>
<pre><code class="lang-http"><span class="hljs-attribute">GET [Organization URI]/api/data/v9.2/contacts?$select=fullname 
Accept</span>: application/json  
<span class="hljs-attribute">OData-MaxVersion</span>: 4.0  
<span class="hljs-attribute">OData-Version</span>: 4.0
<span class="hljs-attribute">If-None-Match</span>: null
</code></pre>
<p>Sample response of above query</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"@odata.context"</span>: <span class="hljs-string">"https://[Organization URI].crm8.dynamics.com/api/data/v9.2/$metadata#contacts(fullname)"</span>,
    <span class="hljs-attr">"value"</span>: [
        {
            <span class="hljs-attr">"@odata.etag"</span>: <span class="hljs-string">"W/\"867043\""</span>,
            <span class="hljs-attr">"fullname"</span>: <span class="hljs-string">"Yvonne McKay (sample)"</span>,
            <span class="hljs-attr">"contactid"</span>: <span class="hljs-string">"fe2a6a27-89fd-e711-a836-000d3a33a7cb"</span>
        },
        {
            <span class="hljs-attr">"@odata.etag"</span>: <span class="hljs-string">"W/\"866666\""</span>,
            <span class="hljs-attr">"fullname"</span>: <span class="hljs-string">"अनामिका अग्रवाल (नमूना)"</span>,
            <span class="hljs-attr">"contactid"</span>: <span class="hljs-string">"540b4637-a636-ec11-8c65-000d3af2b6a6"</span>
        }
    ]
}
</code></pre>
<p>If all attributes need to be retrieved, remove $select clause like shown below.</p>
<pre><code class="lang-http"><span class="hljs-attribute">GET [Organization URI]/api/data/v9.2/contacts
Accept</span>: application/json  
<span class="hljs-attribute">OData-MaxVersion</span>: 4.0  
<span class="hljs-attribute">OData-Version</span>: 4.0
<span class="hljs-attribute">If-None-Match</span>: null
</code></pre>
<p>Sample response of above query</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"@odata.context"</span>: <span class="hljs-string">"https://[Organization URI].crm8.dynamics.com/api/data/v9.2/$metadata#contacts"</span>,
    <span class="hljs-attr">"value"</span>: [
        {
            <span class="hljs-attr">"@odata.etag"</span>: <span class="hljs-string">"W/\"867043\""</span>,
            <span class="hljs-attr">"customertypecode"</span>: <span class="hljs-number">1</span>,
            <span class="hljs-attr">"address2_addresstypecode"</span>: <span class="hljs-number">1</span>,
            <span class="hljs-attr">"merged"</span>: <span class="hljs-literal">false</span>,
            <span class="hljs-attr">"territorycode"</span>: <span class="hljs-number">1</span>
            ...
            ...
        }
    ]
}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Anatomy Of HTTP Request For Dataverse Web API]]></title><description><![CDATA[Here we will discuss requirements and standards for creating HTTP Requests for Microsoft Dataverse Web API. This API uses OData protocol which is also maintained by Microsoft. While currently OData v8 is already in preview, Dataverse Web API is stuck...]]></description><link>https://dev.ashishvishwakarma.com/anatomy-of-http-request-for-dataverse-web-api</link><guid isPermaLink="true">https://dev.ashishvishwakarma.com/anatomy-of-http-request-for-dataverse-web-api</guid><dc:creator><![CDATA[Ashish Vishwakarma]]></dc:creator><pubDate>Thu, 20 Jan 2022 16:53:48 GMT</pubDate><content:encoded><![CDATA[<p>Here we will discuss requirements and standards for creating HTTP Requests for Microsoft Dataverse Web API. This API uses <a target="_blank" href="https://www.odata.org/">OData</a> protocol which is also maintained by Microsoft. While currently OData v8 is already in preview, Dataverse Web API is stuck in time of OData v4 days, it means that all the latest features can not be used, but this is still justifiable based on how data is maintained inside Dataverse, Microsoft will update the OData version when it's the right time. Let's have a look what all we need for making Dataverse Web API Call. </p>
<h2 id="heading-1-endpoint">1. Endpoint</h2>
<p>Like any other Web API you need to get endpoint for your Datavserse environment. Format from Dataverse Web API endpoint is shown below.</p>
<pre><code>https://<span class="hljs-tag">&lt;<span class="hljs-name">Environment</span> <span class="hljs-attr">Name</span>&gt;</span>.<span class="hljs-tag">&lt;<span class="hljs-name">CRM</span> <span class="hljs-attr">Region</span> <span class="hljs-attr">URL</span>&gt;</span>/api/data/<span class="hljs-tag">&lt;<span class="hljs-name">api</span> <span class="hljs-attr">version</span>&gt;</span>/
</code></pre><p>Suppose, your environment is <code>"creativebiz"</code>, your CRM region is India(i.e <code>crm8.dynamics.com</code>) &amp; current  api version is <code>v9.2</code> then your endpoint should look like </p>
<pre><code class="lang-http"><span class="hljs-attribute">https://creativebiz.crm8.dynamics.com/api/data/v9.2/</span>
</code></pre>
<p>Here you can notice 3 things</p>
<h3 id="heading-a-environment-name">a. Environment Name</h3>
<p>This is set at the time of Dataverse environment creation, if you don't define it then it will be generated randomly. You should pay attention on this while creating a new Dataverse Environment.</p>
<h3 id="heading-b-api-version">b. API Version</h3>
<p>Current Dataverse Web API version is v9.2, hence <code>v9.2</code> is shown in example. You can even make call with full build numbers like <code>v9.2.786.1008</code> or a supported previous version number like <code>v9.1</code>.</p>
<h3 id="heading-c-region">c. Region</h3>
<p>Microsoft assigns Region based on your geographical location, refer below table.  <a target="_blank" href="https://arunpotti.com/2021/03/15/dynamics-365-crm-online-regions-list/">source</a> </p>
<div class="hn-table">
<table>
<thead>
<tr>
<td></td><td>Region</td><td>URL</td></tr>
</thead>
<tbody>
<tr>
<td></td><td>North America (NAM)</td><td>crm.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>United States Government Community Cloud(US GCC) High</td><td>crm.microsoftdynamics.us</td><td></td></tr>
<tr>
<td></td><td>Microsoft Cloud Germany (DEU)</td><td>crm.microsoftdynamics.de</td><td></td></tr>
<tr>
<td></td><td>South America (LATAM/ SAM)</td><td>crm2.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>Canada (CAN)</td><td>crm3.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>Europe, Middle East, Africa (EMEA/ EUR)</td><td>crm4.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>Asia Pacific (APAC/ APJ)</td><td>crm5.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>Australia (OCE)</td><td>crm6.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>Japan (JPN)</td><td>crm7.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>India (IND)</td><td>crm8.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>North America 2 (US Gov GCC)</td><td>crm9.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>United Kingdom (UK/ GBR)</td><td>crm11.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>France (FRA)</td><td>crm12.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>South Africa (ZAF)</td><td>crm14.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>United Arab Emirates (UAE)</td><td>crm15.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>Germany (GER)</td><td>crm16.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>Switzerland (CHE)</td><td>crm17.dynamics.com</td><td></td></tr>
<tr>
<td></td><td>China (CHN)</td><td>crm.dynamics.cn</td><td></td></tr>
</tbody>
</table>
</div><h2 id="heading-2-http-headers">2. HTTP Headers</h2>
<p>Dataverse Web API supports many HTTP headers, some are standard HTTP &amp; OData headers while few are proprietary headers for specific operations which will be discussed in respective recipes.
Microsoft suggests below 4 headers as standard to be added with all the requests made against Dataverse Web API. </p>
<pre><code class="lang-http"><span class="hljs-attribute">Accept</span>: application/json 
<span class="hljs-attribute">OData-MaxVersion</span>: 4.0 
<span class="hljs-attribute">OData-Version</span>: 4.0
<span class="hljs-attribute">If-None-Match</span>: null
</code></pre>
<h2 id="heading-3-http-method">3. HTTP Method</h2>
<p>At the time of writing this Dataverse Web API supports below 5 HTTP methods.</p>
<pre><code class="lang-http"><span class="hljs-attribute">GET
POST
PATCH
PUT
DELETE</span>
</code></pre>
<h2 id="heading-4-authentication">4. Authentication</h2>
<p>All requests should be authenticated by Azure AD. Refer <a target="_blank" href="https://www.ashishvishwakarma.com/Dynamics-365-Single-Tenant-Server-2-Server-Authentication-Azure-Active-Directory-Access-Token/">here</a>  for detailed setup steps.</p>
<h2 id="heading-5-permissionauthentication">5. Permission/Authentication</h2>
<p>Requests can not be anonymous, there must be some user to make the request and that user should have appropriate permission to perform specific operations.</p>
<p>I further recipes these basics will be used.</p>
]]></content:encoded></item><item><title><![CDATA[Get Specific Field Change History from AuditDetail in Dynamics 365]]></title><description><![CDATA[In a requirement we were asked to show one specific field change history in a custom portal written in PHP, our immediate action was to call RetrieveAttributeChangeHistory via WebApi but if was just returning the list of value history without any oth...]]></description><link>https://dev.ashishvishwakarma.com/get-specific-field-change-history-from-auditdetail-in-dynamics-365</link><guid isPermaLink="true">https://dev.ashishvishwakarma.com/get-specific-field-change-history-from-auditdetail-in-dynamics-365</guid><dc:creator><![CDATA[Ashish Vishwakarma]]></dc:creator><pubDate>Sun, 31 Jan 2021 04:00:00 GMT</pubDate><content:encoded><![CDATA[<p>In a requirement we were asked to show one specific field change history in a custom portal written in PHP, our immediate action was to call <strong>RetrieveAttributeChangeHistory</strong> via WebApi but if was just returning the list of value history without any other fields but getting CahngedOn and ChangedBy field was our requirement. (see details in github issue <a target="_blank" href="https://github.com/MicrosoftDocs/dynamics-365-customer-engagement/issues/1183">here</a>).</p>
<p>We finally headed to our good old CRM SDK libraries and written code in C# then access this via Dynamics 365 WebApi using Dynamics 365 Custom Action.</p>
<p>I’m sharing here core logic, it can be used either in Action or any other place where CRM SDK C# libraries can be consumed.</p>
<h3 id="model-class-to-get-history-as-a-list">Model class to get history as a list</h3>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">FieldHistory</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> ChangedBy { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> DateTime ChangedOn { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Oldvalue { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> NewValue { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre><h3 id="function-to-get-and-parse-field-history">Function to get and parse field history</h3>
<p>Below code is using <strong>FormattedValues</strong> which retrieve user readable component out of OptionSet and EntityReference fields, this can be modified according to your requirements.</p>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-keyword">List</span>&lt;FieldHistory&gt; GetFieldHistory(<span class="hljs-keyword">string</span> entityLogicalName, Guid recordId, <span class="hljs-keyword">string</span> fieldName, IOrganizationService service)
{
    <span class="hljs-comment">// Retrieving change history fro given attribute/field</span>
    <span class="hljs-keyword">var</span> attributeChangeHistoryRequest = <span class="hljs-keyword">new</span> RetrieveAttributeChangeHistoryRequest
    {
        Target = <span class="hljs-keyword">new</span> EntityReference(entityLogicalName, recordId),
        AttributeLogicalName = fieldName
    };

    <span class="hljs-keyword">var</span> attributeChangeHistoryResponse = (RetrieveAttributeChangeHistoryResponse)service.Execute(attributeChangeHistoryRequest);
    <span class="hljs-keyword">var</span> details = attributeChangeHistoryResponse.AuditDetailCollection;

    <span class="hljs-comment">// List to store changes</span>
    <span class="hljs-keyword">var</span> fieldHistory = <span class="hljs-keyword">new</span> <span class="hljs-keyword">List</span>&lt;FieldHistory&gt;();

    <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> detail in details.AuditDetails)
    {
        <span class="hljs-keyword">var</span> detailType = detail.GetType();
        <span class="hljs-keyword">if</span> (detailType == typeof(AttributeAuditDetail))
        {
            <span class="hljs-comment">// retrieve old &amp; new value of each action of each audit change from AttributeAuditDetail</span>
            <span class="hljs-keyword">var</span> attributeDetail = (AttributeAuditDetail)detail;

            <span class="hljs-keyword">var</span> userName = attributeDetail.AuditRecord.GetAttributeValue&lt;EntityReference&gt;(<span class="hljs-string">"userid"</span>).Name;
            <span class="hljs-keyword">var</span> changedOn = attributeDetail.AuditRecord.GetAttributeValue&lt;DateTime&gt;(<span class="hljs-string">"createdon"</span>);
            <span class="hljs-keyword">var</span> newValue = attributeDetail.NewValue.FormattedValues[fieldName];
            <span class="hljs-keyword">var</span> oldValue = attributeDetail.OldValue?.FormattedValues[fieldName];

            fieldHistory.Add(<span class="hljs-keyword">new</span> FieldHistory
            {
                ChangedBy = userName,
                ChangedOn = changedOn,
                Oldvalue = oldValue,
                NewValue = newValue
            });

            <span class="hljs-keyword">return</span> fieldHistory;
        }
    }
}
</code></pre><p>If you observe I have use safe navigation operator for var oldValue = attributeDetail.OldValue?.FormattedValues[fieldName]; this is because for the first occurrence OldValue will always remain null.</p>
<p>This code is <strong>good</strong> if we are using in C# specific requirement, while it’s a <strong>workaround</strong> if we need field history via WebAPI. Let’s keep an eye in <a target="_blank" href="https://docs.microsoft.com/en-us/dynamics365/customer-engagement/web-api/retrieveattributechangehistory">official documentation</a> and in this <a target="_blank" href="https://github.com/MicrosoftDocs/dynamics-365-customer-engagement/issues/1183">issue</a> if Microsoft returns more meaningful response in future.</p>
<p>I hope this helps.</p>
]]></content:encoded></item><item><title><![CDATA[Quick Local WebServer with IIS Express]]></title><description><![CDATA[TL;DR Download server.bat, place it in your folder, Run it and get going.
Web Development has changed drastically in recent years. These days even most of the front-end requires to be run from a web-server, and if like me you are not a full-time web ...]]></description><link>https://dev.ashishvishwakarma.com/quick-local-webserver-with-iis-express</link><guid isPermaLink="true">https://dev.ashishvishwakarma.com/quick-local-webserver-with-iis-express</guid><category><![CDATA[web]]></category><category><![CDATA[server]]></category><dc:creator><![CDATA[Ashish Vishwakarma]]></dc:creator><pubDate>Fri, 10 Apr 2020 18:48:01 GMT</pubDate><content:encoded><![CDATA[<p><strong>TL;DR</strong> Download <a target="_blank" href="../assets/2020-04-11/server.bat">server.bat</a>, place it in your folder, Run it and get going.</p>
<p>Web Development has changed drastically in recent years. These days even most of the front-end requires to be run from a web-server, and if like me you are not a full-time web developer, you may find a hard time setting up a local webserver.</p>
<p>Here’s good news! Many frameworks and languages provide out of the box web-server which can be utilized for the task. I mainly code on Microsoft related technologies so IISExpress is already installed in my machine, which can be used as a local web-server using this command.</p>
<pre><code>C:\&gt; &lt;<span class="hljs-type">path</span> <span class="hljs-keyword">to</span> iisexpress.exe&gt; /<span class="hljs-type">path</span>:&lt;absolute <span class="hljs-type">path</span> <span class="hljs-keyword">to</span> folder&gt; /port:&lt;port <span class="hljs-keyword">to</span> be used&gt;
</code></pre><p>Suppose your IISExpress is installed at the default location, your front-end code is kept at C:\MyWeb and port to be used is 8000, then the command will look like this.</p>
<pre><code><span class="hljs-attribute">C</span>:\&gt; <span class="hljs-string">"C:\Program Files (x86)\IIS Express\iisexpress.exe"</span> /<span class="hljs-attribute">path</span>:<span class="hljs-attribute">C</span>:\MyWeb /<span class="hljs-attribute">port</span>:<span class="hljs-number">8000</span>
</code></pre><p>To avoid typing this command every time I moved this to a batch file with a small tweak like below, where <code>%cd%</code> picks your current directory.</p>
<pre><code>"C:\Program Files (x86)\IIS Express\iisexpress.exe" /<span class="hljs-type">path</span>:%cd% /port:<span class="hljs-number">8000</span>
</code></pre><p>You simply paste this batch file in your folder and get going. Executing this batch file will start a local webserver at the current folder with port 8000. Access your webpage at http://localhost:8000</p>
<p><img src="../assets/2020-04-11/local-web-server.png" alt="local-web-server" /></p>
<p><a target="_blank" href="../assets/2020-04-11/server.bat">Download server.bat batch file here.</a></p>
<p>To find local webserver options for other languages &amp; frameworks follow this awesome Github Gist. <a target="_blank" href="https://gist.github.com/willurd/5720255">Big list of HTTP static server one-liners</a></p>
]]></content:encoded></item><item><title><![CDATA[Connect CrmServiceClient using Azure AD App Client ID & Client Secret for C# SDK]]></title><description><![CDATA[After depecation announcemnt of Dynamics 2011 Organization Service Endpoint in late 2018 and recommendation on using OAuth authentication & Dynamics 365 WebAPI, there was uncertainity for developers who were using/planning to use 3rd party integartio...]]></description><link>https://dev.ashishvishwakarma.com/connect-crmserviceclient-using-azure-ad-app-client-id-and-client-secret-for-c-sdk</link><guid isPermaLink="true">https://dev.ashishvishwakarma.com/connect-crmserviceclient-using-azure-ad-app-client-id-and-client-secret-for-c-sdk</guid><category><![CDATA[Azure]]></category><category><![CDATA[sdk]]></category><category><![CDATA[crm]]></category><dc:creator><![CDATA[Ashish Vishwakarma]]></dc:creator><pubDate>Sun, 01 Mar 2020 18:48:01 GMT</pubDate><content:encoded><![CDATA[<p>After depecation announcemnt of Dynamics 2011 Organization Service Endpoint in late 2018 and recommendation on using OAuth authentication &amp; Dynamics 365 WebAPI, there was uncertainity for developers who were using/planning to use 3rd party integartion using C# SDK.</p>
<p>Ref: <a target="_blank" href="https://crmtipoftheday.com/1155/the-clock-is-ticking-on-your-endpoint/">https://crmtipoftheday.com/1155/the-clock-is-ticking-on-your-endpoint/</a></p>
<p>Ref: <a target="_blank" href="https://community.dynamics.com/crm/f/microsoft-dynamics-crm-forum/311096/is-organization-service-is-going-to-be-deprecated">https://community.dynamics.com/crm/f/microsoft-dynamics-crm-forum/311096/is-organization-service-is-going-to-be-deprecated</a></p>
<p>Finally, <code>CrmServiceClient</code> provides option to connect to organization service using Client Id &amp; Client Secret. Let’s try it out.</p>
<h3 id="why-to-use-client-id-and-client-secret-to-authenticate">Why to use Client ID &amp; Client Secret to Authenticate</h3>
<ul>
<li>Only minor code chanegs required in existing code.</li>
<li>OAuth is safer than using password based authenticaton.</li>
<li>Save user licencing cost by using Application User</li>
</ul>
<h3 id="sample-code">Sample Code</h3>
<p>As part of initial setup Application User &amp; Azure AD App is required if you don’t have it already please refer to Step 1 &amp; Step 2 in <a target="_blank" href="https://www.ashishvishwakarma.com/Dynamics-365-Single-Tenant-Server-2-Server-Authentication-Azure-Active-Directory-Access-Token/">this artice.</a> Once you have all the details, prepare connection string as shown below and use <strong>AuthType=ClientSecret</strong> here.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> IOrganizationService <span class="hljs-title">GetOrganizationServiceClientSecret</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> clientId, <span class="hljs-keyword">string</span> clientSecret, <span class="hljs-keyword">string</span> organizationUri</span>)</span>
{
    <span class="hljs-keyword">try</span>
    {
        <span class="hljs-keyword">var</span> conn = <span class="hljs-keyword">new</span> CrmServiceClient(<span class="hljs-string">$@"AuthType=ClientSecret;url=<span class="hljs-subst">{organizationUri}</span>;ClientId=<span class="hljs-subst">{clientId}</span>;ClientSecret=<span class="hljs-subst">{clientSecret}</span>"</span>);

        <span class="hljs-keyword">return</span> conn.OrganizationWebProxyClient != <span class="hljs-literal">null</span> ? conn.OrganizationWebProxyClient : (IOrganizationService)conn.OrganizationServiceProxy;
    }
    <span class="hljs-keyword">catch</span> (Exception ex)
    {
        Console.WriteLine(<span class="hljs-string">"Error while connecting to CRM "</span> + ex.Message);
        Console.ReadKey();
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    }
}

IOrganizationService orgService = GetOrganizationServiceClientSecret(
                 <span class="hljs-string">"&lt;Client Id obtained from Azure AD App&gt;"</span>,
                 <span class="hljs-string">"&lt;Client Secret obtained from Azure AD App&gt;"</span>,
                 <span class="hljs-string">"&lt;Organization Uri&gt;"</span>);

<span class="hljs-keyword">var</span> response = orgService.Execute(<span class="hljs-keyword">new</span> WhoAmIRequest());
</code></pre><p>All the necessary packages should be installed, package <strong>Microsoft.CrmSdk.XrmTooling.CoreAssembly</strong> version should be 9.1.0.13 or higher in order to connect using ClientSecret. <a target="_blank" href="https://www.nuget.org/packages/Microsoft.CrmSdk.XrmTooling.CoreAssembly/9.1.0.38/">see release notes.</a></p>
<p><img src="../assets/2020-03-02/packages.png" alt="nuget-packages" /></p>
<p>You can find this code on my <a target="_blank" href="https://github.com/AshV/Dynamics365ConsoleCaller">GitHub.</a></p>
<p>Feel free to get back in case of any suggestions/queries.</p>
]]></content:encoded></item><item><title><![CDATA[Exploring Power Apps Dataflows and Migrating Data from a WebAPI]]></title><description><![CDATA[Finally, Dynamics 365/Power Platform has it’s own no code ETL tool. It is called Data Flows(formerly Data Integration). Let’s explore and try it out.
Navigate to https://make.powerapps.com and select your environment here or create a new one, I’m sel...]]></description><link>https://dev.ashishvishwakarma.com/exploring-power-apps-dataflows-and-migrating-data-from-a-webapi</link><guid isPermaLink="true">https://dev.ashishvishwakarma.com/exploring-power-apps-dataflows-and-migrating-data-from-a-webapi</guid><dc:creator><![CDATA[Ashish Vishwakarma]]></dc:creator><pubDate>Sat, 01 Feb 2020 18:48:01 GMT</pubDate><content:encoded><![CDATA[<p>Finally, Dynamics 365/Power Platform has it’s own no code ETL tool. It is called <strong>Data Flows</strong>(formerly Data Integration). Let’s explore and try it out.</p>
<p>Navigate to <a target="_blank" href="https://make.powerapps.com">https://make.powerapps.com</a> and select your environment here or create a new one, I’m selecting my Dynamics 365 environment.</p>
<p><img src="./assets/2020-02-02/Select-Environment.jpg" alt /></p>
<p>Navigate to Dataflows on the left pane, expand Data and click Dataflows.</p>
<p><img src="./assets/2020-02-02/Open-Dataflows.jpg" alt /></p>
<p>Click on + New dataflow here.</p>
<p><img src="./assets/2020-02-02/Create-New-Dataflow.jpg" alt /></p>
<p>Provide a name for dataflow, we are going to migrate a WebAPI, hence I’d call it WebAPI Dataflow.</p>
<p><img src="./assets/2020-02-02/New-Dataflow.jpg" alt /></p>
<p>Dataflow supports a huge set of data sources to choose from, but mostly they require a gateway if they are outside of your tenant. Select WebAPI here, we will try a publically available API.</p>
<p><img src="./assets/2020-02-02/Select-WebAPI-Data-Source.jpg" alt /></p>
<p>I’m going to use <a target="_blank" href="https://api.itbook.store/">https://api.itbook.store/</a> which a publically available API, you may try with other APIs as well. This API provides an endpoint <a target="_blank" href="https://api.itbook.store/1.0/new">https://api.itbook.store/1.0/new</a> which provides newly released books, we will use this to store all the latest books data in an entity.</p>
<p><img src="./assets/2020-02-02/It-Ebook-API-New.jpg" alt /></p>
<p>Have a look at the sample response from this endpoint. We are going to store books as entity records.</p>
<pre><code>{
    <span class="hljs-attr">"error"</span>: <span class="hljs-string">"0"</span>,
    <span class="hljs-attr">"total"</span>: <span class="hljs-string">"10"</span>,
    <span class="hljs-attr">"books"</span>: [
        {
            <span class="hljs-attr">"title"</span>: <span class="hljs-string">"AI Blueprints"</span>,
            <span class="hljs-attr">"subtitle"</span>: <span class="hljs-string">"How to build and deploy AI business projects"</span>,
            <span class="hljs-attr">"isbn13"</span>: <span class="hljs-string">"9781788992879"</span>,
            <span class="hljs-attr">"price"</span>: <span class="hljs-string">"$31.99"</span>,
            <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://itbook.store/img/books/9781788992879.png"</span>,
            <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://itbook.store/books/9781788992879"</span>
        },
        {
            <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Data Analysis with Python"</span>,
            <span class="hljs-attr">"subtitle"</span>: <span class="hljs-string">"A Modern Approach"</span>,
            <span class="hljs-attr">"isbn13"</span>: <span class="hljs-string">"9781789950069"</span>,
            <span class="hljs-attr">"price"</span>: <span class="hljs-string">"$31.99"</span>,
            <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://itbook.store/img/books/9781789950069.png"</span>,
            <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://itbook.store/books/9781789950069"</span>
        },
        {
            <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Build Reactive Websites with RxJS"</span>,
            <span class="hljs-attr">"subtitle"</span>: <span class="hljs-string">"Master Observables and Wrangle Events"</span>,
            <span class="hljs-attr">"isbn13"</span>: <span class="hljs-string">"9781680502954"</span>,
            <span class="hljs-attr">"price"</span>: <span class="hljs-string">"$28.98"</span>,
            <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://itbook.store/img/books/9781680502954.png"</span>,
            <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://itbook.store/books/9781680502954"</span>
        },
        {
            <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Forge Your Future with Open Source"</span>,
            <span class="hljs-attr">"subtitle"</span>: <span class="hljs-string">"Build Your Skills. Build Your Network. Build the Future of Technology"</span>,
            <span class="hljs-attr">"isbn13"</span>: <span class="hljs-string">"9781680503012"</span>,
            <span class="hljs-attr">"price"</span>: <span class="hljs-string">"$26.18"</span>,
            <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://itbook.store/img/books/9781680503012.png"</span>,
            <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://itbook.store/books/9781680503012"</span>
        },
        {
            <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Xcode Treasures"</span>,
            <span class="hljs-attr">"subtitle"</span>: <span class="hljs-string">"Master the Tools to Design, Build, and Distribute Great Apps"</span>,
            <span class="hljs-attr">"isbn13"</span>: <span class="hljs-string">"9781680505863"</span>,
            <span class="hljs-attr">"price"</span>: <span class="hljs-string">"$22.03"</span>,
            <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://itbook.store/img/books/9781680505863.png"</span>,
            <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://itbook.store/books/9781680505863"</span>
        },
        {
            <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Learning C++ by Building Games with Unreal Engine 4, 2nd Edition"</span>,
            <span class="hljs-attr">"subtitle"</span>: <span class="hljs-string">"A beginner's guide to learning 3D game development with C++ and UE4"</span>,
            <span class="hljs-attr">"isbn13"</span>: <span class="hljs-string">"9781788476249"</span>,
            <span class="hljs-attr">"price"</span>: <span class="hljs-string">"$44.99"</span>,
            <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://itbook.store/img/books/9781788476249.png"</span>,
            <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://itbook.store/books/9781788476249"</span>
        },
        {
            <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Apache Kafka Quick Start Guide"</span>,
            <span class="hljs-attr">"subtitle"</span>: <span class="hljs-string">"Leverage Apache Kafka 2.0 to simplify real-time data processing for distributed applications"</span>,
            <span class="hljs-attr">"isbn13"</span>: <span class="hljs-string">"9781788997829"</span>,
            <span class="hljs-attr">"price"</span>: <span class="hljs-string">"$23.99"</span>,
            <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://itbook.store/img/books/9781788997829.png"</span>,
            <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://itbook.store/books/9781788997829"</span>
        },
        {
            <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Hands-On Dark Web Analysis"</span>,
            <span class="hljs-attr">"subtitle"</span>: <span class="hljs-string">"Learn what goes on in the Dark Web, and how to work with it"</span>,
            <span class="hljs-attr">"isbn13"</span>: <span class="hljs-string">"9781789133363"</span>,
            <span class="hljs-attr">"price"</span>: <span class="hljs-string">"$29.99"</span>,
            <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://itbook.store/img/books/9781789133363.png"</span>,
            <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://itbook.store/books/9781789133363"</span>
        },
        {
            <span class="hljs-attr">"title"</span>: <span class="hljs-string">"CentOS Quick Start Guide"</span>,
            <span class="hljs-attr">"subtitle"</span>: <span class="hljs-string">"Get up and running with CentOS server administration"</span>,
            <span class="hljs-attr">"isbn13"</span>: <span class="hljs-string">"9781789344875"</span>,
            <span class="hljs-attr">"price"</span>: <span class="hljs-string">"$31.99"</span>,
            <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://itbook.store/img/books/9781789344875.png"</span>,
            <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://itbook.store/books/9781789344875"</span>
        },
        {
            <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Machine Learning with Apache Spark Quick Start Guide"</span>,
            <span class="hljs-attr">"subtitle"</span>: <span class="hljs-string">"Uncover patterns, derive actionable insights, and learn from big data using MLlib"</span>,
            <span class="hljs-attr">"isbn13"</span>: <span class="hljs-string">"9781789346565"</span>,
            <span class="hljs-attr">"price"</span>: <span class="hljs-string">"$29.99"</span>,
            <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://itbook.store/img/books/9781789346565.png"</span>,
            <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://itbook.store/books/9781789346565"</span>
        }
    ]
}
</code></pre><p>Now head back to PowerApps screen and provide <a target="_blank" href="https://api.itbook.store/1.0/new">https://api.itbook.store/1.0/new</a> in the URL text box, you may observe that Authentication kind is set as Anonymous because it’s publically available, otherwise either a gateway is required or API should be in the same tenant. Click Next.</p>
<p><img src="./assets/2020-02-02/Provide-WebAPI-URL.jpg" alt /></p>
<p>Let’s understand the appearing Power Query screen, we are going to spend quite some time�here.</p>
<ul>
<li>On top Header menu has options related to transforming the data.</li>
<li>Power Query is auto-generated when we apply operations to data, but this can be edited manually also. Power Query is widely used in Power BI.</li>
<li>Below that our current state of data is shown, we can interact with it and transform as per our requirement.</li>
<li>On right pane all the Applied Steps are listed, we can traverse back and forth here to update any changes made earlier.</li>
</ul>
<p><img src="./assets/2020-02-02/Power-Query-Screen.jpg" alt /></p>
<p>Let’s start transforming now, click on books[list], it will expand the records.</p>
<p><img src="./assets/2020-02-02/Transforming-1.jpg" alt /></p>
<p>Click on Convert to table button here and then Ok in appearing popup, it will transform your list of records as a table.</p>
<p><img src="./assets/2020-02-02/Transforming-2.jpg" alt /></p>
<p><img src="./assets/2020-02-02/Convert-To-Table.jpg" alt /></p>
<p>Click on the arrow button as shown in the image and uncheck the checkbox ‘Use original column name as prefix’ which makes column names tidier. Click Ok, it will expand all the column data.</p>
<p><img src="./assets/2020-02-02/No-Prefix.jpg" alt /></p>
<p>By default, all columns datatype are treated as raw(string), We can specify it explicitly also, let’s try this with ‘isbn13’ column so we can use this as Key later. Select the column, expand the ‘Transform column’ and click ‘Detect data type’.</p>
<p><img src="./assets/2020-02-02/Detect-Datatype.jpg" alt /></p>
<p>You can see on Query that it is detected as Int64.</p>
<p><img src="./assets/2020-02-02/Datatype-Query.jpg" alt /></p>
<p>Change it to ‘text’ manually.</p>
<pre><code><span class="hljs-keyword">Table</span>.TransformColumnTypes(#"Expanded Column1", \{\{"isbn13", <span class="hljs-keyword">type</span> <span class="hljs-type">text</span>\}\})
</code></pre><p>You may observe all the transformations are being recorded on the right pane. Now the transformation part is completed, click on Next to proceed to load.</p>
<p><img src="./assets/2020-02-02/Applied-Steps.jpg" alt /></p>
<p>You can either load data to an existing entity or create a new entity here and then load. Choosing an existing entity gives more control over the prefix name and solution. Here we are going to load data to a new entity.</p>
<p><img src="./assets/2020-02-02/Load-to-Existing-Entity.jpg" alt /></p>
<p>Select ‘Load to new entity’, specify name and display name for the entity. In the field mapping section we will specify isbn13 as Key field and title as Primary name field, before doing that change field type as Text for both of them and then set as Key and Primary name fields. Now click Next to schedule.</p>
<p><img src="./assets/2020-02-02/Entity-Field-Mapping.jpg" alt /></p>
<p>We can choose to run our dataflow manually or can be scheduled at regular intervals, which can be triggered manually as well. Once scheduled click Create which will start creating entity and loading the data.</p>
<p><img src="./assets/2020-02-02/Scheduling.jpg" alt /></p>
<p>Once it is loaded click Done and verify this loaded data in Dynamics 365 Advanced Find or Model-driven Power App.</p>
<p><img src="./assets/2020-02-02/Loaded-Data.jpg" alt /></p>
<p>To Refresh any dataflow manually you can click Refresh as shown in the image.</p>
<p><img src="./assets/2020-02-02/Refresh-Manually.jpg" alt /></p>
<p>Please feel free to get back in case of any feedback or query.</p>
<p>Cheers!</p>
]]></content:encoded></item><item><title><![CDATA[Generate Access Token for Dynamics 365 Single Tenant Server to Server Authentication]]></title><description><![CDATA[In Dynamics 365 integration scenarios most of the times we need to authenticate only single tenant. Since now Dynamics 365 authentication only through Azure AD (for online instances) is recommended let’s see how to do it. To achieve this first of all...]]></description><link>https://dev.ashishvishwakarma.com/generate-access-token-for-dynamics-365-single-tenant-server-to-server-authentication--deleted</link><guid isPermaLink="true">https://dev.ashishvishwakarma.com/generate-access-token-for-dynamics-365-single-tenant-server-to-server-authentication--deleted</guid><dc:creator><![CDATA[Ashish Vishwakarma]]></dc:creator><pubDate>Fri, 28 Dec 2018 18:48:01 GMT</pubDate><content:encoded><![CDATA[<p><img src="../assets/2018-12-29/microsoft-dynamics-365-banner.jpg" alt="Generate Access Token for Dynamics 365 Single Tenant Server to Server Authentication" /></p>
<p>In Dynamics 365 integration scenarios most of the times we need to authenticate only single tenant. Since now Dynamics 365 authentication only through Azure AD (for online instances) is recommended let’s see how to do it. To achieve this first of all we need to create App in Azure Active Directory and good news is that you don’t need Azure subscription to try this out, your Dynamics 365 free trial is enough.</p>
<p>These 4 steps are involved to implement this, you can always jump to next step if know current step. This topic may not be very new to everyone, but when I got to implement the same recently it took me few hours to make it work, because of recent of frequent Azure updates or outdated content maybe. which leads me to write this.</p>
<ol>
<li>Create &amp; configureApp in Azure Active Directory</li>
<li>Create User in Azure AD and Configure it as Application User in Dynamics 365</li>
<li>Write C# code with ADAL(Active Directory Authentication Library) to generate Access Token</li>
<li>Making requests to Dynamics 365 with above generated Access Token</li>
</ol>
<h2 id="step-1-create-azure-ad-app">Step 1: Create Azure AD App</h2>
<ul>
<li>Navigate to Azure(https://portal.azure.com).</li>
<li><p>On left menu click on <strong>Azure Active Directory</strong> -&gt; App registrations(Preview) =&gt; <strong>+ New registration</strong>, We will use Preview version only because it has more straight forward options and going forward this only is going to be default option. <img src="../assets/2018-12-29/create-azure-ad-app.png" alt="create-azure-ad-app" /></p>
</li>
<li><p>Give some Name to your App, and for account type select <em>Accounts in this organizational directory only</em> because we need it for single tenant only. <img src="../assets/2018-12-29/single-tenant-app.png" alt="single-tenant-app" /></p>
</li>
<li><p>Once App is created, click on API permissions to add new permission for your app. <img src="../assets/2018-12-29/adding-new-permissions.png" alt="adding-new-permissions" /></p>
</li>
<li><p>Select Dynamics CRM here. <img src="../assets/2018-12-29/dynamics-crm-permission.png" alt="dynamics-crm-permission" /></p>
</li>
<li><p>Check user_impersonation box in upcoming screen and click <em>Add permissions</em> <img src="../assets/2018-12-29/user-impersonation.png" alt="user-impersonation" /></p>
</li>
<li><p>These permission require admin consent, click on <strong>Grant admin consent for your-org</strong> button and confirm it. You need administrator role to do it.</p>
</li>
<li><img src="../assets/2018-12-29/grant-admin-consent.png" alt="grant-admin-consent" /></li>
</ul>
<p><strong>Now your App is created, we need three things to use further from here.</strong></p>
<ol>
<li>Application Id aka Client Id</li>
<li>Tenant Id</li>
<li><p>Client Secret</p>
</li>
<li><p>Application Id &amp; Tenant Id you can grab from App Overview. <img src="../assets/2018-12-29/app-overview.png" alt="app-overview" /></p>
</li>
<li><p>To generate Client Secret go to <strong>Certificates &amp; secrets</strong> and then <strong>+ New client secret</strong>, Give some description and select validity of your secret, click <strong>Add</strong>. <img src="../assets/2018-12-29/client-secret.png" alt="client-secret" /></p>
</li>
<li><p>Client Secret is something which you should keep secret, that why you can see this only once after generation, copy it and keep it safe to use later.</p>
</li>
<li><img src="../assets/2018-12-29/generated-secret.png" alt="generated-secret" /></li>
</ol>
<h2 id="step-2-create-application-user">Step 2: Create Application User</h2>
<ul>
<li>You need to create a new user, all CRM Api calls will be made on behalf of this user.</li>
<li>This user does not require Dynamics 365 license.</li>
<li>This user should be created from Azure(https://portal.azure.com), not from Office Portal(https://admin.microsoft.com)</li>
<li>Navigate to Azure -&gt; Azure Active Directory -&gt; Users, Click on <strong>+ New user</strong>.</li>
</ul>
<p><img src="../assets/2018-12-29/new-app-user.png" alt="new-app-user" /></p>
<ul>
<li>Here Username field must be has same domain name as your org.</li>
<li>Once this user is create, Go to your Dynamics 365 instance.</li>
<li>Navigate to Dynamics 365 -&gt; Settings -&gt; Security, Click on Users here.</li>
<li><p>Change view to Application Users &amp; click on <strong>+ NEW</strong> to create new Application User. <img src="../assets/2018-12-29/set-view-as-application-user.png" alt="set-view-as-application-user" /></p>
</li>
<li><p>You may need to set form also as Application User if it’s not coming by default. <img src="../assets/2018-12-29/set-form-as-application-user.png" alt="set-form-as-application-user" /></p>
</li>
<li><p>Here Application ID must be the same as Azure AD App created in previous step. Username &amp; email you can keep same as the one created in Azure AD. Though it’s not necessary to be the same, I have tried with different name also. Once you save it Application ID URI &amp; Azure AD Object ID will auto populate. <img src="../assets/2018-12-29/new-app-user-d365.png" alt="new-app-user-d365" /></p>
</li>
<li><p>Now you need to assign <strong>security role</strong> to this user to perform operation on desired records, I’ve seen in many blogs that this user must have a custom security role, so you can copy some existing role and assign it. But when I tried with <strong>OOB security role</strong> it was still working.</p>
</li>
</ul>
<h2 id="step-3-get-access-token-with-adal">Step 3: Get Access Token with ADAL</h2>
<ul>
<li><p>Create new project in Visual Studio and add ADAL package via NuGet. <img src="../assets/2018-12-29/ADAL-NuGet.png" alt="ADAL-NuGet.png" /></p>
</li>
<li><p>Create below shown method and replace Application Id, Client Secret, Tenant Id &amp; your organization Url in appropriate place.</p>
</li>
</ul>
<h2 id="step-4-consuming-access-token">Step 4: Consuming Access Token</h2>
<ul>
<li><p>You have access token now, you can make request to your Dynamics 365 by including this to your HTTP requests, see below method.</p>
<p>public static async Task CrmRequest(HttpMethod httpMethod, string requestUri, string body = null)
{</p>
<pre><code>var accessToken = await AccessTokenGenerator();
var client = <span class="hljs-built_in">new</span> HttpClient();
var msg = <span class="hljs-built_in">new</span> HttpRequestMessage(httpMethod, requestUri);
msg.Headers.<span class="hljs-keyword">Add</span>("OData-MaxVersion", "4.0");
msg.Headers.<span class="hljs-keyword">Add</span>("OData-Version", "4.0");
msg.Headers.<span class="hljs-keyword">Add</span>("Prefer", "odata.include-annotations=\"*\"");

// <span class="hljs-keyword">Passing</span> AccessToken <span class="hljs-keyword">in</span> Authentication <span class="hljs-keyword">header</span>
msg.Headers.<span class="hljs-keyword">Add</span>("Authentication", $"Bearer {accessToken}");

<span class="hljs-keyword">if</span> (body != <span class="hljs-keyword">null</span>)
    msg.Content = <span class="hljs-built_in">new</span> StringContent(body, UnicodeEncoding.UTF8, "application/json");

<span class="hljs-keyword">return</span> await client.SendAsync(msg);
</code></pre><p>}</p>
</li>
</ul>
<ul>
<li><p>You can make different requests using above method, here is an example for retrieving all contacts with GET.</p>
<p>var contacts = CrmRequest(</p>
<pre><code>HttpMethod.<span class="hljs-keyword">Get</span>, 
"https://efrig.api.crm8.dynamics.com/api/data/v9.1/contacts")
.Result.Content.ReadAsStringAsync();
</code></pre></li>
</ul>
<h2 id="full-code-replace-your-azure-credentials-before-executing">Full Code (Replace your Azure Credentials before executing)</h2>
<pre><code><span class="hljs-keyword">using</span> Microsoft.IdentityModel.Clients.ActiveDirectory;
<span class="hljs-keyword">using</span> System.Net.Http;
<span class="hljs-keyword">using</span> System.Text;
<span class="hljs-keyword">using</span> System.Threading.Tasks;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">D365S2S</span>
{
    <span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>
    {
        <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>[] args</span>)</span>
        {
            <span class="hljs-keyword">var</span> contacts = CrmRequest(
                HttpMethod.Get,
                <span class="hljs-string">"https://efrig.api.crm8.dynamics.com/api/data/v9.1/contacts"</span>)
                .Result.Content.ReadAsStringAsync();
            <span class="hljs-comment">// Similarly you can make POST, PATCH &amp; DELETE requests</span>
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">async</span> Task&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">AccessTokenGenerator</span>(<span class="hljs-params"></span>)</span>
        {
            <span class="hljs-keyword">string</span> clientId = <span class="hljs-string">"13950f0e-0000-4e2f-0000-b923302c4338"</span>; <span class="hljs-comment">// Your Azure AD Application ID</span>
            <span class="hljs-keyword">string</span> clientSecret = <span class="hljs-string">"0^C#%0000DR7/#Z[-.m5aYO00000000$"</span>; <span class="hljs-comment">// Client secret generated in your App</span>
            <span class="hljs-keyword">string</span> authority = <span class="hljs-string">"https://login.microsoftonline.com/ceb48f70-0000-1111-0000-9170f6a706a6"</span>; <span class="hljs-comment">// Azure AD App Tenant ID</span>
            <span class="hljs-keyword">string</span> resourceUrl = <span class="hljs-string">"https://efrig.crm8.dynamics.com"</span>; <span class="hljs-comment">// Your Dynamics 365 Organization URL</span>

            <span class="hljs-keyword">var</span> credentials = <span class="hljs-keyword">new</span> ClientCredential(clientId, clientSecret);
            <span class="hljs-keyword">var</span> authContext = <span class="hljs-keyword">new</span> Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(authority);
            <span class="hljs-keyword">var</span> result = <span class="hljs-keyword">await</span> authContext.AcquireTokenAsync(resourceUrl, credentials);
            <span class="hljs-keyword">return</span> result.AccessToken;
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">async</span> Task&lt;HttpResponseMessage&gt; <span class="hljs-title">CrmRequest</span>(<span class="hljs-params">HttpMethod httpMethod, <span class="hljs-keyword">string</span> requestUri, <span class="hljs-keyword">string</span> body = <span class="hljs-literal">null</span></span>)</span>
        {
            <span class="hljs-comment">// Acquiring Access Token</span>
            <span class="hljs-keyword">var</span> accessToken = <span class="hljs-keyword">await</span> AccessTokenGenerator();

            <span class="hljs-keyword">var</span> client = <span class="hljs-keyword">new</span> HttpClient();
            <span class="hljs-keyword">var</span> message = <span class="hljs-keyword">new</span> HttpRequestMessage(httpMethod, requestUri);

            <span class="hljs-comment">// OData related headers</span>
            message.Headers.Add(<span class="hljs-string">"OData-MaxVersion"</span>, <span class="hljs-string">"4.0"</span>);
            message.Headers.Add(<span class="hljs-string">"OData-Version"</span>, <span class="hljs-string">"4.0"</span>);
            message.Headers.Add(<span class="hljs-string">"Prefer"</span>, <span class="hljs-string">"odata.include-annotations=\"*\""</span>);

            <span class="hljs-comment">// Passing AccessToken in Authentication header</span>
            message.Headers.Add(<span class="hljs-string">"Authorization"</span>, <span class="hljs-string">$"Bearer <span class="hljs-subst">{accessToken}</span>"</span>);

            <span class="hljs-comment">// Adding body content in HTTP request </span>
            <span class="hljs-keyword">if</span> (body != <span class="hljs-literal">null</span>)
                message.Content = <span class="hljs-keyword">new</span> StringContent(body, UnicodeEncoding.UTF8, <span class="hljs-string">"application/json"</span>);

            <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> client.SendAsync(message);
        }
    }
}
</code></pre><blockquote>
<p>Hope it helps, feel free to get in touch for any query/suggestions.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Parsing Customer Journey Workflow Definition JSON with Linq.js in Dynamics 365 for Marketing]]></title><description><![CDATA[In new Dynamics 365 Apps many configurations and data are being saved as JSON, rather than creating relationships between entities or saving as XML. Customer Journey is one of those entity, this provides visual designer like shown below to design wor...]]></description><link>https://dev.ashishvishwakarma.com/parsing-customer-journey-workflow-definition-json-with-linqjs-in-dynamics-365-for-marketing</link><guid isPermaLink="true">https://dev.ashishvishwakarma.com/parsing-customer-journey-workflow-definition-json-with-linqjs-in-dynamics-365-for-marketing</guid><dc:creator><![CDATA[Ashish Vishwakarma]]></dc:creator><pubDate>Wed, 31 Oct 2018 18:48:01 GMT</pubDate><content:encoded><![CDATA[<p>In new Dynamics 365 Apps many configurations and data are being saved as JSON, rather than creating relationships between entities or saving as XML. Customer Journey is one of those entity, this provides visual designer like shown below to design workflow and this is saved as JSON behind the scenes in <strong>msdyncrm_workflowdefinition</strong> column. This workflow has data related to all the components of customer journey and interacton between them.</p>
<p><img src="../assets/2018-11-01/CustomerJourney.png" alt="CustomerJourney" /></p>
<p>Sometimes we need to programatically query that which all records are participating in customer journey workflow. Then we need to parse JSON store in msdyncrm_workflowdefinition field, while doing this in client side <a target="_blank" href="https://www.ashishvishwakarma.com/LINQ-JS-for-Dynamics-365-Developers/">linq.js will make our job easy af</a>.</p>
<p>Below is the code to parse a few components which can be used as it is, or you might need to modify code a bit as per requirement or if you are adding you custom channels to your customer journey. This code snippet is stored as Github Gist at <a target="_blank" href="https://gist.github.com/AshV/b0eb8aef725a8c6670d3c20f80b54029">https://gist.github.com/AshV/b0eb8aef725a8c6670d3c20f80b54029</a>.</p>
<p>In above code I have written a function to filter all the node reference related to provided component, which can be queried further as per requirements. Below given is json for a typical customer journey workflow you can observe outer <strong>ActivityTypeId</strong> is representing type of tile in customer jorney designer while inner <strong>ActivityTypeId</strong> is refering to reocrds in most of the places.</p>
<pre><code>[
    {
        <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"bpf_root"</span>,
        <span class="hljs-attr">"ParentBranchId"</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">"ParentRelationshipType"</span>: <span class="hljs-string">"Default"</span>,
        <span class="hljs-attr">"ActivityId"</span>: <span class="hljs-string">"01"</span>,
        <span class="hljs-attr">"Properties"</span>: {
            <span class="hljs-attr">"Items"</span>: [
                {
                    <span class="hljs-attr">"ItemId"</span>: <span class="hljs-literal">null</span>,
                    <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"bpf_root"</span>,
                    <span class="hljs-attr">"Title"</span>: <span class="hljs-string">"Undefined"</span>,
                    <span class="hljs-attr">"Name"</span>: <span class="hljs-string">"New ActivityTypeName_bpf_root_TitleText"</span>,
                    <span class="hljs-attr">"ActivityItemId"</span>: <span class="hljs-number">0</span>
                },
                {
                    <span class="hljs-attr">"ItemId"</span>: <span class="hljs-literal">null</span>,
                    <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"bpf_root"</span>,
                    <span class="hljs-attr">"Title"</span>: <span class="hljs-string">"Undefined"</span>,
                    <span class="hljs-attr">"Name"</span>: <span class="hljs-string">"New ActivityTypeName_bpf_root_TitleText"</span>,
                    <span class="hljs-attr">"ActivityItemId"</span>: <span class="hljs-number">1</span>
                }
            ]
        }
    },
    {
        <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Segment"</span>,
        <span class="hljs-attr">"ParentActivityId"</span>: <span class="hljs-string">"01"</span>,
        <span class="hljs-attr">"ParentBranchId"</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">"ParentRelationshipType"</span>: <span class="hljs-string">"Default"</span>,
        <span class="hljs-attr">"ActivityId"</span>: <span class="hljs-string">"01_2"</span>,
        <span class="hljs-attr">"Properties"</span>: {
            <span class="hljs-attr">"Items"</span>: [
                {
                    <span class="hljs-attr">"ItemId"</span>: <span class="hljs-literal">null</span>,
                    <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Segment"</span>,
                    <span class="hljs-attr">"Title"</span>: <span class="hljs-string">"Undefined"</span>,
                    <span class="hljs-attr">"Name"</span>: <span class="hljs-string">"my customers"</span>,
                    <span class="hljs-attr">"ActivityItemId"</span>: <span class="hljs-number">8</span>,
                    <span class="hljs-attr">"SegmentMergeMethod"</span>: <span class="hljs-string">"Union"</span>,
                    <span class="hljs-attr">"ContainmentMethod"</span>: <span class="hljs-string">"Inclusion"</span>,
                    <span class="hljs-attr">"Description"</span>: <span class="hljs-string">""</span>
                },
                {
                    <span class="hljs-attr">"ItemId"</span>: <span class="hljs-literal">null</span>,
                    <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"SegmentItem"</span>,
                    <span class="hljs-attr">"Title"</span>: <span class="hljs-string">"Undefined"</span>,
                    <span class="hljs-attr">"Name"</span>: <span class="hljs-string">"New Segment"</span>,
                    <span class="hljs-attr">"ActivityItemId"</span>: <span class="hljs-number">9</span>,
                    <span class="hljs-attr">"ContainmentMethod"</span>: <span class="hljs-string">"Inclusion"</span>,
                    <span class="hljs-attr">"Description"</span>: <span class="hljs-string">""</span>
                }
            ]
        },
        <span class="hljs-attr">"EntityTarget"</span>: <span class="hljs-string">"contact"</span>
    },
    {
        <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Email"</span>,
        <span class="hljs-attr">"ParentActivityId"</span>: <span class="hljs-string">"01_2"</span>,
        <span class="hljs-attr">"ParentBranchId"</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">"ParentRelationshipType"</span>: <span class="hljs-string">"Default"</span>,
        <span class="hljs-attr">"ActivityId"</span>: <span class="hljs-string">"01_2_4"</span>,
        <span class="hljs-attr">"Properties"</span>: {
            <span class="hljs-attr">"Items"</span>: [
                {
                    <span class="hljs-attr">"ItemId"</span>: <span class="hljs-string">"08634d0e-25dc-e811-a965-000d3af2924b"</span>,
                    <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Email"</span>,
                    <span class="hljs-attr">"Title"</span>: <span class="hljs-string">"Undefined"</span>,
                    <span class="hljs-attr">"Name"</span>: <span class="hljs-string">"invite email"</span>,
                    <span class="hljs-attr">"ActivityItemId"</span>: <span class="hljs-number">17</span>,
                    <span class="hljs-attr">"Description"</span>: <span class="hljs-string">""</span>
                },
                {
                    <span class="hljs-attr">"ItemId"</span>: <span class="hljs-literal">null</span>,
                    <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"LandingPage"</span>,
                    <span class="hljs-attr">"Title"</span>: <span class="hljs-string">"Undefined"</span>,
                    <span class="hljs-attr">"Name"</span>: <span class="hljs-string">"event page"</span>,
                    <span class="hljs-attr">"ActivityItemId"</span>: <span class="hljs-number">28</span>,
                    <span class="hljs-attr">"Description"</span>: <span class="hljs-string">""</span>
                }
            ]
        },
        <span class="hljs-attr">"EntityTarget"</span>: <span class="hljs-string">"contact"</span>
    },
    {
        <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Trigger"</span>,
        <span class="hljs-attr">"ParentActivityId"</span>: <span class="hljs-string">"01_2_4_14_19"</span>,
        <span class="hljs-attr">"ParentBranchId"</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">"ParentRelationshipType"</span>: <span class="hljs-string">"Default"</span>,
        <span class="hljs-attr">"ActivityId"</span>: <span class="hljs-string">"01_2_4_7"</span>,
        <span class="hljs-attr">"Properties"</span>: {
            <span class="hljs-attr">"Items"</span>: [
                {
                    <span class="hljs-attr">"ItemId"</span>: <span class="hljs-literal">null</span>,
                    <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Trigger"</span>,
                    <span class="hljs-attr">"Title"</span>: <span class="hljs-string">"Undefined"</span>,
                    <span class="hljs-attr">"Name"</span>: <span class="hljs-string">"registered?"</span>,
                    <span class="hljs-attr">"ActivityItemId"</span>: <span class="hljs-number">38</span>,
                    <span class="hljs-attr">"TimeoutValue"</span>: <span class="hljs-number">5</span>,
                    <span class="hljs-attr">"ConditionExpressions"</span>: [
                        {
                            <span class="hljs-attr">"SourceActivityItemId"</span>: <span class="hljs-string">"28"</span>,
                            <span class="hljs-attr">"Condition"</span>: <span class="hljs-string">"UserRegistered"</span>
                        }
                    ],
                    <span class="hljs-attr">"RuleLogic"</span>: <span class="hljs-string">"AND"</span>,
                    <span class="hljs-attr">"TimeoutUnit"</span>: <span class="hljs-string">"Day"</span>,
                    <span class="hljs-attr">"Description"</span>: <span class="hljs-string">""</span>
                }
            ]
        },
        <span class="hljs-attr">"EntityTarget"</span>: <span class="hljs-string">"contact"</span>
    },
    {
        <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"empty"</span>,
        <span class="hljs-attr">"ParentActivityId"</span>: <span class="hljs-string">"01_2_4_7"</span>,
        <span class="hljs-attr">"ParentBranchId"</span>: <span class="hljs-number">1</span>,
        <span class="hljs-attr">"ParentRelationshipType"</span>: <span class="hljs-string">"NoBranch"</span>,
        <span class="hljs-attr">"ActivityId"</span>: <span class="hljs-string">"01_2_4_7_9"</span>,
        <span class="hljs-attr">"Properties"</span>: {
            <span class="hljs-attr">"Items"</span>: []
        }
    },
    {
        <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"CreateCrmActivity"</span>,
        <span class="hljs-attr">"ParentActivityId"</span>: <span class="hljs-string">"01_2_4_7"</span>,
        <span class="hljs-attr">"ParentBranchId"</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">"ParentRelationshipType"</span>: <span class="hljs-string">"YesBranch"</span>,
        <span class="hljs-attr">"ActivityId"</span>: <span class="hljs-string">"01_2_4_7_11"</span>,
        <span class="hljs-attr">"Properties"</span>: {
            <span class="hljs-attr">"Items"</span>: [
                {
                    <span class="hljs-attr">"ItemId"</span>: <span class="hljs-literal">null</span>,
                    <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"CreateCrmActivity"</span>,
                    <span class="hljs-attr">"Title"</span>: <span class="hljs-string">"Undefined"</span>,
                    <span class="hljs-attr">"Name"</span>: <span class="hljs-string">"follow up call"</span>,
                    <span class="hljs-attr">"ActivityItemId"</span>: <span class="hljs-number">50</span>,
                    <span class="hljs-attr">"TemplateEntityLogicalName"</span>: <span class="hljs-string">"msdyncrm_phonecallactivitymarketingtemplate"</span>,
                    <span class="hljs-attr">"ActivityTypeName"</span>: <span class="hljs-string">"phonecall"</span>,
                    <span class="hljs-attr">"Owner"</span>: <span class="hljs-string">"msdyncrm_customerjourney.ownerid"</span>,
                    <span class="hljs-attr">"Description"</span>: <span class="hljs-string">""</span>
                }
            ]
        },
        <span class="hljs-attr">"EntityTarget"</span>: <span class="hljs-string">"contact"</span>
    },
    {
        <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Email"</span>,
        <span class="hljs-attr">"ParentActivityId"</span>: <span class="hljs-string">"01_2_4_7_11_32"</span>,
        <span class="hljs-attr">"ParentBranchId"</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">"ParentRelationshipType"</span>: <span class="hljs-string">"Default"</span>,
        <span class="hljs-attr">"ActivityId"</span>: <span class="hljs-string">"01_2_4_7_11_26_30"</span>,
        <span class="hljs-attr">"Properties"</span>: {
            <span class="hljs-attr">"Items"</span>: [
                {
                    <span class="hljs-attr">"ItemId"</span>: <span class="hljs-literal">null</span>,
                    <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Email"</span>,
                    <span class="hljs-attr">"Title"</span>: <span class="hljs-string">"Undefined"</span>,
                    <span class="hljs-attr">"Name"</span>: <span class="hljs-string">"thank you"</span>,
                    <span class="hljs-attr">"ActivityItemId"</span>: <span class="hljs-number">80</span>,
                    <span class="hljs-attr">"Description"</span>: <span class="hljs-string">""</span>
                }
            ]
        },
        <span class="hljs-attr">"EntityTarget"</span>: <span class="hljs-string">"contact"</span>
    },
    {
        <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Scheduler"</span>,
        <span class="hljs-attr">"ParentActivityId"</span>: <span class="hljs-string">"01_2_4_7_11"</span>,
        <span class="hljs-attr">"ParentBranchId"</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">"ParentRelationshipType"</span>: <span class="hljs-string">"Default"</span>,
        <span class="hljs-attr">"ActivityId"</span>: <span class="hljs-string">"01_2_4_7_11_32"</span>,
        <span class="hljs-attr">"Properties"</span>: {
            <span class="hljs-attr">"Items"</span>: [
                {
                    <span class="hljs-attr">"ItemId"</span>: <span class="hljs-literal">null</span>,
                    <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Scheduler"</span>,
                    <span class="hljs-attr">"Title"</span>: <span class="hljs-string">"Undefined"</span>,
                    <span class="hljs-attr">"Name"</span>: <span class="hljs-string">"New Scheduler"</span>,
                    <span class="hljs-attr">"ActivityItemId"</span>: <span class="hljs-number">98</span>,
                    <span class="hljs-attr">"WaitUntilMonday"</span>: <span class="hljs-literal">true</span>,
                    <span class="hljs-attr">"WaitUntilTuesday"</span>: <span class="hljs-literal">true</span>,
                    <span class="hljs-attr">"WaitUntilWednesday"</span>: <span class="hljs-literal">true</span>,
                    <span class="hljs-attr">"WaitUntilThursday"</span>: <span class="hljs-literal">true</span>,
                    <span class="hljs-attr">"WaitUntilFriday"</span>: <span class="hljs-literal">true</span>,
                    <span class="hljs-attr">"WaitUntilSaturday"</span>: <span class="hljs-literal">true</span>,
                    <span class="hljs-attr">"WaitUntilSunday"</span>: <span class="hljs-literal">true</span>,
                    <span class="hljs-attr">"WaitUntilFromHour"</span>: <span class="hljs-number">0</span>,
                    <span class="hljs-attr">"WaitUntilFromMinute"</span>: <span class="hljs-number">0</span>,
                    <span class="hljs-attr">"WaitUntilToHour"</span>: <span class="hljs-number">23</span>,
                    <span class="hljs-attr">"WaitUntilToMinute"</span>: <span class="hljs-number">59</span>,
                    <span class="hljs-attr">"OffsetType"</span>: <span class="hljs-string">"Duration"</span>,
                    <span class="hljs-attr">"ScheduledDurationUnit"</span>: <span class="hljs-string">"Minute"</span>,
                    <span class="hljs-attr">"ScheduledHour"</span>: <span class="hljs-number">0</span>,
                    <span class="hljs-attr">"ScheduledMinute"</span>: <span class="hljs-number">0</span>,
                    <span class="hljs-attr">"ScheduledDurationValue"</span>: <span class="hljs-number">0</span>,
                    <span class="hljs-attr">"Description"</span>: <span class="hljs-string">""</span>
                }
            ]
        },
        <span class="hljs-attr">"EntityTarget"</span>: <span class="hljs-string">"contact"</span>
    },
    {
        <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Event"</span>,
        <span class="hljs-attr">"ParentActivityId"</span>: <span class="hljs-string">"01_2_4"</span>,
        <span class="hljs-attr">"ParentBranchId"</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">"ParentRelationshipType"</span>: <span class="hljs-string">"Default"</span>,
        <span class="hljs-attr">"ActivityId"</span>: <span class="hljs-string">"01_2_4_14"</span>,
        <span class="hljs-attr">"Properties"</span>: {
            <span class="hljs-attr">"Items"</span>: [
                {
                    <span class="hljs-attr">"ItemId"</span>: <span class="hljs-string">"306c65eb-18dc-e811-a96a-000d3af29d99"</span>,
                    <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Event"</span>,
                    <span class="hljs-attr">"Title"</span>: <span class="hljs-string">"Undefined"</span>,
                    <span class="hljs-attr">"IsNameSystemDefined"</span>: <span class="hljs-literal">true</span>,
                    <span class="hljs-attr">"Name"</span>: <span class="hljs-string">"New Event"</span>,
                    <span class="hljs-attr">"ActivityItemId"</span>: <span class="hljs-number">65</span>,
                    <span class="hljs-attr">"Description"</span>: <span class="hljs-string">""</span>
                }
            ]
        },
        <span class="hljs-attr">"EntityTarget"</span>: <span class="hljs-string">"contact"</span>
    },
    {
        <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Event"</span>,
        <span class="hljs-attr">"ParentActivityId"</span>: <span class="hljs-string">"01_2_4_14"</span>,
        <span class="hljs-attr">"ParentBranchId"</span>: <span class="hljs-number">0</span>,
        <span class="hljs-attr">"ParentRelationshipType"</span>: <span class="hljs-string">"Default"</span>,
        <span class="hljs-attr">"ActivityId"</span>: <span class="hljs-string">"01_2_4_14_19"</span>,
        <span class="hljs-attr">"Properties"</span>: {
            <span class="hljs-attr">"Items"</span>: [
                {
                    <span class="hljs-attr">"ItemId"</span>: <span class="hljs-literal">null</span>,
                    <span class="hljs-attr">"ActivityTypeId"</span>: <span class="hljs-string">"Event"</span>,
                    <span class="hljs-attr">"Title"</span>: <span class="hljs-string">"Undefined"</span>,
                    <span class="hljs-attr">"IsNameSystemDefined"</span>: <span class="hljs-literal">true</span>,
                    <span class="hljs-attr">"Name"</span>: <span class="hljs-string">"New Event"</span>,
                    <span class="hljs-attr">"ActivityItemId"</span>: <span class="hljs-number">91</span>
                }
            ]
        },
        <span class="hljs-attr">"EntityTarget"</span>: <span class="hljs-string">"contact"</span>
    }
]
</code></pre><p>Hope it helps.</p>
]]></content:encoded></item><item><title><![CDATA[Linq.js for Dynamics 365 Developers]]></title><description><![CDATA[Recently I was working in some large JSON objects in client side javascript where I had to query through it several times as per requirement I was using javascript array’s functions. Then I thought why not use lodash.js or underscore.js I checked ove...]]></description><link>https://dev.ashishvishwakarma.com/linqjs-for-dynamics-365-developers</link><guid isPermaLink="true">https://dev.ashishvishwakarma.com/linqjs-for-dynamics-365-developers</guid><dc:creator><![CDATA[Ashish Vishwakarma]]></dc:creator><pubDate>Mon, 29 Oct 2018 18:48:01 GMT</pubDate><content:encoded><![CDATA[<p>Recently I was working in some large JSON objects in client side javascript where I had to query through it several times as per requirement I was using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype">javascript array’s functions</a>. Then I thought why not use <a target="_blank" href="https://github.com/lodash/lodash/">lodash.js</a> or <a target="_blank" href="https://github.com/jashkenas/underscore">underscore.js</a> I checked over github they are really feature rich and trustworthy, but there was a whole new list of functions and syntax to learn.</p>
<p>Then after few more google search I got sevearal <a target="_blank" href="https://dzone.com/articles/5-linq-javascript-libraries">javascript libraries with LINQ like syntax</a>, after comparing I found <a target="_blank" href="https://github.com/mihaifm/linq">linq.js</a> most promising and even size is lesser when comparing to lodash and underscore.</p>
<p>Library</p>
<p>GZipped size</p>
<p>lodash</p>
<p>~ 24 KB</p>
<p><strong>linq.js</strong></p>
<p><strong>~ 7 KB</strong></p>
<p>underscore</p>
<p>~ 6.6 KB</p>
<blockquote>
<p>linq.js github project link -&gt; <a target="_blank" href="https://github.com/mihaifm/linq">https://github.com/mihaifm/linq</a></p>
</blockquote>
<p>With Linq.js dynamics 365 developers can use their existing knowledge of LINQ in javascript code whith nominal changes. see below examples from their github</p>
<pre><code>// C# LINQ - delegate
Enumerable.Range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)
    .<span class="hljs-keyword">Where</span>(delegate(<span class="hljs-type">int</span> i) { <span class="hljs-keyword">return</span> i % <span class="hljs-number">3</span> == <span class="hljs-number">0</span>; })
    .<span class="hljs-keyword">Select</span>(delegate(<span class="hljs-type">int</span> i) { <span class="hljs-keyword">return</span> i * <span class="hljs-number">10</span>; });

// linq.js - anonymous <span class="hljs-keyword">function</span>
Enumerable.range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)
    .<span class="hljs-keyword">where</span>(<span class="hljs-keyword">function</span>(i) { <span class="hljs-keyword">return</span> i % <span class="hljs-number">3</span> == <span class="hljs-number">0</span>; })
    .<span class="hljs-keyword">select</span>(<span class="hljs-keyword">function</span>(i) { <span class="hljs-keyword">return</span> i * <span class="hljs-number">10</span>; });


// C# LINQ - lambda
Enumerable.Range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>).<span class="hljs-keyword">Where</span>(i =&gt; i % <span class="hljs-number">3</span> == <span class="hljs-number">0</span>).<span class="hljs-keyword">Select</span>(i =&gt; i * <span class="hljs-number">10</span>);

// linq.js - arrow <span class="hljs-keyword">function</span>
Enumerable.range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>).<span class="hljs-keyword">where</span>(i =&gt; i % <span class="hljs-number">3</span> == <span class="hljs-number">0</span>).<span class="hljs-keyword">select</span>(i =&gt; i * <span class="hljs-number">10</span>);


// C# LINQ - anonymous <span class="hljs-keyword">type</span>
<span class="hljs-keyword">array</span>.<span class="hljs-keyword">Select</span>((val, i) =&gt; <span class="hljs-built_in">new</span> { <span class="hljs-keyword">Value</span> = val, <span class="hljs-keyword">Index</span> = i });

// linq.js - <span class="hljs-keyword">object</span> literal
Enumerable.<span class="hljs-keyword">from</span>(<span class="hljs-keyword">array</span>).<span class="hljs-keyword">select</span>((val, i) =&gt; ({ <span class="hljs-keyword">value</span>: val, <span class="hljs-keyword">index</span>: i}));
</code></pre><h3 id="example-with-dynamics-365crm">Example with Dynamics 365/CRM</h3>
<p>Let’s retrieve some data from CRM and query in client side javascript. First of all download and save linq.min.js as a javascript webresource, and save below code as html webresource and change your linq.js webresource name accordingly.</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Trying linq.js<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/WebResources/new_linq.js"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"ClientGlobalContext.js.aspx"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-comment">// to bypass a product bug, ignore this</span>
    <span class="hljs-built_in">window</span>[<span class="hljs-string">"ENTITY_SET_NAMES"</span>] = <span class="hljs-built_in">window</span>[<span class="hljs-string">"ENTITY_SET_NAMES"</span>] || <span class="hljs-string">'{ "account" : "accounts"}'</span>;

    <span class="hljs-comment">// retrieving accoount records</span>
    Xrm.WebApi.retrieveMultipleRecords(<span class="hljs-string">"account"</span>).then(
      <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">result</span>) </span>{
        <span class="hljs-keyword">debugger</span>;
        <span class="hljs-built_in">console</span>.log(result);
        <span class="hljs-comment">// storing all the records to var accounts </span>
        <span class="hljs-keyword">var</span> accounts = result.entities;

        <span class="hljs-comment">// build query filter all records with address1_city == "Redmond"</span>
        <span class="hljs-keyword">var</span> accountsCityRedmond = Enumerable.from(accounts).where(<span class="hljs-function"><span class="hljs-params">a</span> =&gt;</span> a.address1_city == <span class="hljs-string">"Redmond"</span>);
        <span class="hljs-comment">// use toArray(); to evaluate the query</span>
        <span class="hljs-built_in">console</span>.log(accountsCityRedmond.toArray());

        <span class="hljs-comment">// previously built query can be filtered even further</span>
        <span class="hljs-keyword">var</span> accountsCityRedmondCountryColumbia = accountsCityRedmond.where(<span class="hljs-function"><span class="hljs-params">a</span> =&gt;</span> a.address1_country == <span class="hljs-string">"Columbia"</span>).select(<span class="hljs-function"><span class="hljs-params">w</span> =&gt;</span> w.websiteurl);
        <span class="hljs-comment">// and can be evaluated anytime with .toArray()</span>
        <span class="hljs-built_in">console</span>.log(accountsCityRedmondCountryColumbia.toArray());
      },
      <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">error</span>) </span>{
        <span class="hljs-built_in">console</span>.log(error.message);
      }
    );
  </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
</code></pre><p>Run above HTML web resource in browser &amp; press F12 to see output, it would be similar to below shown output, I have run this code in newly created trial instance of dynamics 365.</p>
<blockquote>
<p>Go through code comments to understand it better.</p>
</blockquote>
<p><img src="../assets/2018-10-30/output.png" alt="output" /></p>
<p>Hope it helps. Feel free to ask any questons.</p>
]]></content:encoded></item><item><title><![CDATA[Querying N:N Relationship Intersect Enity with FetchXML and Dynamics 365 WebAPI]]></title><description><![CDATA[In a recent requirement I had to query some data from N:N relationship in client side javascript. I achieved it with fetch XML & WebAPI here for example I’ll be using User & Security Role entity.
For creating N:N relationships between tables itersect...]]></description><link>https://dev.ashishvishwakarma.com/querying-nn-relationship-intersect-enity-with-fetchxml-and-dynamics-365-webapi</link><guid isPermaLink="true">https://dev.ashishvishwakarma.com/querying-nn-relationship-intersect-enity-with-fetchxml-and-dynamics-365-webapi</guid><dc:creator><![CDATA[Ashish Vishwakarma]]></dc:creator><pubDate>Sat, 20 Oct 2018 18:48:01 GMT</pubDate><content:encoded><![CDATA[<p>In a recent requirement I had to query some data from N:N relationship in client side javascript. I achieved it with fetch XML &amp; WebAPI here for example I’ll be using <strong>User</strong> &amp; <strong>Security Role</strong> entity.</p>
<p>For creating N:N relationships between tables itersect tables are used which usually has 3 columns It’s own <strong>primary key</strong>, first table’s <strong>primary key</strong> &amp; second table’s <strong>primary key</strong>. In dynamics 365 GUIDs are used as primary key so each row conatins 3 GUIDs with given data.</p>
<p>To execute fetchXML, dynamics 365 webAPI requires entity’s plural name, but intersect tables don’t have that so we need to link with one of participating entity in fetchXML to query intersect entity.</p>
<blockquote>
<p>Syntax: WebAPI Endpoint + / + Entity Plural Name + ?fetchXml= + Your fetchXml here</p>
</blockquote>
<p><a target="_blank" href="https://www.ashishvishwakarma.com/Execute-fetchXml-WebAPI-Dynamics-365-Using-JavaScript-Example/">Find more here about executing fetchXml with WebAPI</a></p>
<p>You need to form fetchXML like this, here entity could be either of <strong>User</strong> or <strong>Security Role</strong>, their logical names are <strong>systemuser</strong> &amp; <strong>role</strong> resplectivey. Relationship entity name can be found in N:N relationship in solutions. (refer image)</p>
<blockquote>
<p>Syntax:</p>
</blockquote>
<pre><code>&lt;<span class="hljs-keyword">fetch</span>&gt;
   &lt;entity <span class="hljs-type">name</span>="Entity Name"&gt;
      &lt;<span class="hljs-keyword">attribute</span> <span class="hljs-type">name</span>="Entity Logical ID" /&gt;
      &lt;link-entity <span class="hljs-type">name</span>="Relationship Entity Name" <span class="hljs-keyword">from</span>="Entity ID" <span class="hljs-keyword">to</span>="Entity ID" <span class="hljs-keyword">intersect</span>="true"&gt;
         &lt;<span class="hljs-keyword">all</span>-attributes /&gt;
      &lt;/link-entity&gt;
   &lt;/entity&gt;
&lt;/<span class="hljs-keyword">fetch</span>&gt;
</code></pre><blockquote>
<p>Images:Find Relationship Entity Name</p>
</blockquote>
<p><img src="../assets/2018-10-21/N-N.png" alt="N:N Relationships" /></p>
<p><img src="../assets/2018-10-21/Relationship.png" alt="Relationship Name" /></p>
<blockquote>
<p>Create FetchXML</p>
</blockquote>
<p>FetchXml can be written against any of the participating entity, in this case <strong>User</strong> &amp; <strong>Security Role</strong>. It should be executed accordingly in webAPI with same entity’s plural name which is used in fetchXML. See below.</p>
<p>For <strong>Security Role</strong> =&gt; OrgURL/api/data/v9.0/<strong>roles</strong>?…</p>
<p>For <strong>User</strong> =&gt; OrgURL/api/data/v9.0/<strong>systemusers</strong>?…</p>
<pre><code>&lt;<span class="hljs-keyword">fetch</span>&gt;
  &lt;entity <span class="hljs-type">name</span>="role"&gt;
    &lt;<span class="hljs-keyword">attribute</span> <span class="hljs-type">name</span>="roleid" /&gt;
    &lt;link-entity <span class="hljs-type">name</span>="systemuserroles" <span class="hljs-keyword">from</span>="roleid" <span class="hljs-keyword">to</span>="roleid" <span class="hljs-keyword">intersect</span>="true"&gt;
     &lt;<span class="hljs-keyword">all</span>-attributes/&gt;
    &lt;/link-entity&gt;
  &lt;/entity&gt;
&lt;/<span class="hljs-keyword">fetch</span>&gt;


&lt;<span class="hljs-keyword">fetch</span>&gt;
  &lt;entity <span class="hljs-type">name</span>="systemuser"&gt;
    &lt;<span class="hljs-keyword">attribute</span> <span class="hljs-type">name</span>="systemuserid" /&gt;
    &lt;link-entity <span class="hljs-type">name</span>="systemuserroles" <span class="hljs-keyword">from</span>="systemuserid" <span class="hljs-keyword">to</span>="systemuserid" <span class="hljs-keyword">intersect</span>="true"&gt;
     &lt;<span class="hljs-keyword">all</span>-attributes/&gt;
    &lt;/link-entity&gt;
  &lt;/entity&gt;
&lt;/<span class="hljs-keyword">fetch</span>&gt;
</code></pre><p><a target="_blank" href="https://www.ashishvishwakarma.com/FetchXmlTester/">Click here to use Fetch XML Tester to verify created query</a></p>
<blockquote>
<p>Output: it would look similar</p>
</blockquote>
<pre><code>{
   <span class="hljs-attr">"@odata.context"</span>:<span class="hljs-string">"https://ashv.crm.dynamics.com/api/data/v8.2/$metadata#roles(roleid)"</span>,
   <span class="hljs-attr">"value"</span>:[
      {
         <span class="hljs-attr">"@odata.etag"</span>:<span class="hljs-string">"W/\"1003197\""</span>,
         <span class="hljs-attr">"roleid"</span>:<span class="hljs-string">"e9133cb3-92e5-41c1-a242-9d17098e5f7b"</span>,
         <span class="hljs-attr">"systemuserroles1_x002e_systemuserroleid"</span>:<span class="hljs-string">"1b22830d-93c0-e811-a960-000d3af0375c"</span>,
         <span class="hljs-attr">"systemuserroles1_x002e_roleid"</span>:<span class="hljs-string">"e9133cb3-92e5-41c1-a242-9d17098e5f7b"</span>,
         <span class="hljs-attr">"systemuserroles1_x002e_systemuserid"</span>:<span class="hljs-string">"e4613b07-93c0-e811-a960-000d3af06590"</span>
      },
      {
         <span class="hljs-attr">"@odata.etag"</span>:<span class="hljs-string">"W/\"1003198\""</span>,
         <span class="hljs-attr">"roleid"</span>:<span class="hljs-string">"1a71447c-8751-4bf6-9800-a53faa4258f3"</span>,
         <span class="hljs-attr">"systemuserroles1_x002e_systemuserroleid"</span>:<span class="hljs-string">"bc1c140d-93c0-e811-a962-000d3af04fc2"</span>,
         <span class="hljs-attr">"systemuserroles1_x002e_roleid"</span>:<span class="hljs-string">"1a71447c-8751-4bf6-9800-a53faa4258f3"</span>,
         <span class="hljs-attr">"systemuserroles1_x002e_systemuserid"</span>:<span class="hljs-string">"e4613b07-93c0-e811-a960-000d3af06590"</span>
      }
   ]
}
</code></pre><p>Hope it helps.</p>
]]></content:encoded></item></channel></rss>