<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rob vanBrandenburg</title>
    <description>The latest articles on DEV Community by Rob vanBrandenburg (@robvanb).</description>
    <link>https://dev.to/robvanb</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F614572%2F1f4ef675-5d8b-4c42-afcf-40bc18fc98f3.jpeg</url>
      <title>DEV Community: Rob vanBrandenburg</title>
      <link>https://dev.to/robvanb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/robvanb"/>
    <language>en</language>
    <item>
      <title>Dynamics 365 (E-)Commerce development Proof of Concept (2)</title>
      <dc:creator>Rob vanBrandenburg</dc:creator>
      <pubDate>Fri, 14 May 2021 19:29:16 +0000</pubDate>
      <link>https://dev.to/robvanb/dynamics-365-e-commerce-development-proof-of-concept-2-50k0</link>
      <guid>https://dev.to/robvanb/dynamics-365-e-commerce-development-proof-of-concept-2-50k0</guid>
      <description>&lt;p&gt;This is a follow up on &lt;a href="https://dev.to/robvanb/dynamics-365-e-commerce-development-proof-of-concept-1d05"&gt;this&lt;/a&gt; post.&lt;/p&gt;

&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;In the first part we saw how we can extend the CRT to include additional fields in the extension properties, and how to surface that in your own 'Dynamics 365 Commerce - Ecom' custom module.&lt;br&gt;
In this section I'm going to add that field to the 'Add to cart' process.&lt;br&gt;
If you recall, we added an 'Is Warranty' flag to the product table, and we want to produce a message to the end user when they add this item to their cart. It will inform them that the item does not have warranty, and asks them to confirm that they want to buy it.&lt;/p&gt;
&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;p&gt;Since we are going to add logic to the cart (buybox), we need to be able to mimic adding items to the cart. However, that is not easy when you don't have a full blown Ecom site linked to your dev box.&lt;br&gt;
I think technically it should be possible by setting up a &lt;a href="https://docs.microsoft.com/en-us/dynamics365/commerce/e-commerce-extensibility/test-page-mock"&gt;page mock&lt;/a&gt;, but I could not get this to work.&lt;/p&gt;

&lt;p&gt;However, you can actually use your Test environment's Ecom site for this.&lt;br&gt;
By configuring your .env file to use your Test environment's Ecom site and server, you can use all the site's functionality and data setup while running your Ecom mods locally. &lt;/p&gt;

&lt;p&gt;To do this, point all the variables in your .env file to the test environment.&lt;br&gt;
Then when you access https://:4000 it will render test site and all its data, but loads the code locally. &lt;br&gt;
We'll see further below that we use a custom theme to extend the functionality, and by specifying the theme in our url (with a parameter) we can run the custom code.&lt;/p&gt;
&lt;h1&gt;
  
  
  Implementation
&lt;/h1&gt;

&lt;p&gt;Since I want to add a dialog/message box to the 'add to cart' process, I initially thought I had to change the buybox module.&lt;br&gt;
However Sam Jarawan from Micsrosoft pointed to an easier solution:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---YMe90Bu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b4d39rodshi609000a4j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---YMe90Bu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b4d39rodshi609000a4j.png" alt="Quote Sam"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6RWYI0FW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ygpdvgypblerwv73w1yz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6RWYI0FW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ygpdvgypblerwv73w1yz.jpg" alt="code_sample_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This poses the question; how do we override this?&lt;/p&gt;

&lt;p&gt;If you must change any logic in a component, you can use the command-line interface (CLI) &lt;a href="https://docs.microsoft.com/en-us/dynamics365/commerce/e-commerce-extensibility/cli-command-reference#add-component-override"&gt;add-component-override&lt;/a&gt; command to override the component for a selected theme. &lt;/p&gt;

&lt;p&gt;See &lt;a href="https://docs.microsoft.com/en-us/dynamics365/commerce/e-commerce-extensibility/override-theme-component"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First we need to either &lt;a href="https://docs.microsoft.com/en-us/dynamics365/commerce/e-commerce-extensibility/extend-theme"&gt;create or extend a theme&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Create a new theme using the CLI. (You do this in your Visual Code terminal window):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn mdsyn365 add-theme itk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then modify the theme definition so it extends the standard Fabrikam theme:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SEpYfJT0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xsh445lkvm1e4z5lf6vn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SEpYfJT0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xsh445lkvm1e4z5lf6vn.png" alt="extend_fabrikam_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure to include the styles per &lt;a href="https://docs.microsoft.com/en-us/dynamics365/commerce/e-commerce-extensibility/extend-theme#include-base-theme-styles"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now that we have a theme, we can add our &lt;a href="https://docs.microsoft.com/en-us/dynamics365/commerce/e-commerce-extensibility/override-theme-component"&gt;component override&lt;/a&gt; to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn msdyn365 add-component-override itk AddToCart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command above will copy the component to our themes' "views\components" folder:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ixFsQCV0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6do6py3fr3o2vkrsewr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ixFsQCV0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6do6py3fr3o2vkrsewr2.png" alt="component_override_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will need to update the imports, as the default paths are no longer valid.&lt;br&gt;
From:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--idlHYqUq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tvmhmrvilwpvi0wvb5hg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--idlHYqUq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tvmhmrvilwpvi0wvb5hg.png" alt="component_override_update_imports_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KvjFvBoQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dd61k14ldtctgp8uf4c6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KvjFvBoQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dd61k14ldtctgp8uf4c6.png" alt="component_override_update_imports_2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets make sure that our new code is executed, and that we can do something when an item is added to the cart. For testing we add a simple alert to the code:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d29NLcRf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/14tkqt3syk917it5rhl4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d29NLcRf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/14tkqt3syk917it5rhl4.png" alt="test_alert_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We start the local server:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn start&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Then fire up the browser, navigate to a PDP page, make sure you select the new theme by modifying the URL, and add the item to the bag:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TDEc3Vez--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0fvy3vrwwxoiauswf67t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TDEc3Vez--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0fvy3vrwwxoiauswf67t.png" alt="test_alert_2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beauty! It works!&lt;/p&gt;

&lt;p&gt;Next step: Use the new field in the alert message.&lt;/p&gt;

&lt;p&gt;To do this, we modify the code in our component override :&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x4-McHna--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b2slor6dm2qcb28t5aud.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x4-McHna--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b2slor6dm2qcb28t5aud.jpg" alt="code_sample_2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we now access the pdp page again using our theme, and add the item to the cart, we see this:&lt;br&gt;
(Make sure you use an item that does NOT have the custom warranty flag set)&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bp0stQNM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8dv08vx25dnoo9wdr824.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bp0stQNM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8dv08vx25dnoo9wdr824.jpg" alt="test_msg_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then if we test again, but this time using an item that &lt;em&gt;does&lt;/em&gt; have the custom warranty flag set, we do not get the message.&lt;/p&gt;

&lt;p&gt;The code needs to be adjusted to actually add, or not add the item to the cart based on the user's response, but the example at least shows the concept.&lt;/p&gt;

&lt;p&gt;Rob.&lt;/p&gt;

</description>
      <category>dynamics365</category>
      <category>d365</category>
      <category>dynamics</category>
      <category>ecommerce</category>
    </item>
    <item>
      <title>D365 F&amp;O and PowerApps (2)</title>
      <dc:creator>Rob vanBrandenburg</dc:creator>
      <pubDate>Wed, 12 May 2021 12:54:44 +0000</pubDate>
      <link>https://dev.to/robvanb/d365-f-o-and-powerapps-2-27eb</link>
      <guid>https://dev.to/robvanb/d365-f-o-and-powerapps-2-27eb</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;This is part 2 of using PowerApps with Microsoft Dynamics 365 Finance and Operations. Part 1 is &lt;a href="https://dev.to/robvanb/d365-f-o-and-powerapps-3m1k"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is going to be a short post, as there is not much to it.&lt;br&gt;
As seen in &lt;a href="https://dev.to/robvanb/d365-f-o-and-powerapps-3m1k"&gt;part 1&lt;/a&gt;, you can link to a (canvas) PowerApp from the D365 F&amp;amp;O UI by using the 'PowerApp' button.&lt;br&gt;
However, you can also 'embed' the (canvas) PowerApp in the UI, but this has to be done through actual F&amp;amp;O development.&lt;/p&gt;

&lt;p&gt;First, this doesn't make a lot of sense. The whole idea of the NoCode/LowCode PowerApps is that you do NOT need a developer (and consequent downtime and deployment).&lt;br&gt;
But since the option is there, I figured I'd try it out.&lt;/p&gt;

&lt;p&gt;The official documentation is here:&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/fin-ops/get-started/embed-power-apps#developer-modeling-a-canvas-app-on-a-form" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/fin-ops/get-started/embed-power-apps#developer-modeling-a-canvas-app-on-a-form&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer&lt;/em&gt;: I know the example below makes no business sense. I'm showing sales order lines in the PowerApp that are already present in the F&amp;amp;O form that I add the App to. But since I already had the App from part 1, I figured I'd just reuse it to show the concept.&lt;/p&gt;

&lt;h1&gt;
  
  
  Adding the App to a screen (form)
&lt;/h1&gt;

&lt;p&gt;The actual dev task is very simple. For this example we will be adding the App from part 1 in a new tab in the 'Sales Orders' inquiry form. ('Retail and Commerce -&amp;gt; Inquiries and Reports -&amp;gt; Sales Orders').&lt;/p&gt;

&lt;p&gt;The form name is 'MCRSalesTableOrderHistory', so we first create an extension to that form in Visual Studio.&lt;br&gt;
Then we simply add a tab page, and add a 'PowerAppsHost' control to the page.&lt;br&gt;
In the properties we set the AppId and the field that we want to pass to the App as the key. (Review &lt;a href="https://dev.to/robvanb/d365-f-o-and-powerapps-3m1k"&gt;Part 1&lt;/a&gt; for details)&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fknjemcct1h5poknli9p3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fknjemcct1h5poknli9p3.jpg" alt="VS_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The scaling of the App in the UI is pretty terrible. I manually set the height and width in the control's properties, but it still renders it with a very tiny font. &lt;br&gt;
I have not tried to modify the actual App to use a larger font, but in my opinion this should not be necessary.&lt;br&gt;
In any case, it &lt;em&gt;does&lt;/em&gt; work, the order lines of the order I selected in the main grid are displayed in the PowerApp.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funurc82d4dzxpccmtba8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funurc82d4dzxpccmtba8.jpg" alt="FO_form_2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you see where I set the properties to try and make it bigger (did not work):&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj59cw50rlixrix907w44.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj59cw50rlixrix907w44.jpg" alt="VS_2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;You can add embedded PowerApps directly to the F&amp;amp;O UI. It works. However, I have trouble finding a scenario where you would want to do this.&lt;br&gt;
The only thing I can think of is when you have a PowerApp that serves up data/functionality of an external (non-F&amp;amp;O) system.&lt;br&gt;
But still the rendering in the UI looks pretty bad.&lt;/p&gt;

</description>
      <category>dynamics365</category>
      <category>d365</category>
      <category>dynamic</category>
      <category>powerapps</category>
    </item>
    <item>
      <title>D365 F&amp;O and PowerApps (1)</title>
      <dc:creator>Rob vanBrandenburg</dc:creator>
      <pubDate>Thu, 06 May 2021 15:57:11 +0000</pubDate>
      <link>https://dev.to/robvanb/d365-f-o-and-powerapps-3m1k</link>
      <guid>https://dev.to/robvanb/d365-f-o-and-powerapps-3m1k</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;You can now use Microsoft PowerApps with D365 Finance and Operations. (D365 Supply Chain Management, Finance, Commerce)&lt;br&gt;
I always struggled with finding a business case for doing this. Why not just customize F&amp;amp;O?&lt;br&gt;
But I actually came up with a scenario that I think could be useful.&lt;br&gt;
Read on if you are interested.&lt;/p&gt;
&lt;h1&gt;
  
  
  Business Case
&lt;/h1&gt;

&lt;p&gt;Sometimes you want to quickly see what items are on a sales order. You don't need all the bells and whistles, dates, categories, what have you. You just want to see what's on that order as far as items/products go.&lt;br&gt;
Right now, you will need to go to the 'All Sales Orders' screen, select the order from the grid, then go to the lines, wait until all the stuff you DON'T need is loaded, and then discover you selected the wrong order, and have to start all over again.&lt;/p&gt;

&lt;p&gt;What if I could just bring up a super simple screen that ONLY shows the item, description and qty for the order I selected?&lt;br&gt;
Enter PowerApps.&lt;/p&gt;

&lt;p&gt;This posts outlines the steps to complete the above scenario. Let's get started.&lt;/p&gt;

&lt;p&gt;I got most of the info from the link below, and the helpful &lt;br&gt;
"Finance and Operations Insider Program" Yammer community.&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/fin-ops/get-started/embed-power-apps#adding-an-embedded-canvas-app-from-power-apps-to-a-page"&gt;https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/fin-ops/get-started/embed-power-apps#adding-an-embedded-canvas-app-from-power-apps-to-a-page&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Creating the App
&lt;/h1&gt;

&lt;p&gt;To create your App, make your way to make.powerapps.com and log in.&lt;br&gt;
First we need to create a connection, select the 'Connections' node in the left pane and select 'New connection':&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oH9fQkns--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gnmggybe2see2p7jq7uo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oH9fQkns--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gnmggybe2see2p7jq7uo.png" alt="1 create connection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the FinOps connector and click 'Create':&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YmyMeakC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h41f550bphe8sjtambsp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YmyMeakC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h41f550bphe8sjtambsp.png" alt="2 create connection 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can create our app. &lt;br&gt;
Click on 'Apps' in the left pane and create a canvas app:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XJhJ_Um5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u1itvie23cf6ynej0fn3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XJhJ_Um5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u1itvie23cf6ynej0fn3.png" alt="3 create app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can either start with a 'Table' (Entity) and have a base layout generated based on the data (you do this by clicking on the right arrow) - or start with a blank app.&lt;br&gt;
Since we're building a super simple app, I'm starting with a blank app:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Bk2iE48H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0iu0xf7f78lw87aanu0z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Bk2iE48H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0iu0xf7f78lw87aanu0z.png" alt="4 create app 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First we add our data source. Click on the 'Data' icon on the left, then "Add Data". Drop down the 'Connectors' section and select the F&amp;amp;O connection you just created: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RAwWqtoY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nis0y9s9k9avkl9dg870.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RAwWqtoY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nis0y9s9k9avkl9dg870.png" alt="5 create app 3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will list the available F&amp;amp;O instances in the 'Choose a dataset' window that comes up. Select the one you want to connect to, and then select the table (= F&amp;amp;O Data Entity - ) you want to connect to.&lt;br&gt;
In this example we want to see sales order lines, so we're picking the 'CDSSalesOrderLinesV2' table, and click 'Connect':&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jhyI-LUO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7lsmys5v8123l72h7kt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jhyI-LUO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7lsmys5v8123l72h7kt.png" alt="Select Entity"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Provide an app Name, hit 'CTRL-S' to save, hit the 'back' arrow once saved, and close the Data pane.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f8M4ADIa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cyoqltc0xzni9e0c6ptt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f8M4ADIa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cyoqltc0xzni9e0c6ptt.png" alt="Name and save"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's add some data to our form.&lt;br&gt;
Select the 'Insert' tab and click 'Data table', then select the data source you just added:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--glDMkHOL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cianbdk5ttpx4mt8cfwh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--glDMkHOL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cianbdk5ttpx4mt8cfwh.png" alt="Select Datasource"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you add this, the app will actually load the data, so be patient.&lt;br&gt;
It shows a set of default fields on the grid with their data.&lt;br&gt;
We will change these fields so the grid has the ones we need.&lt;/p&gt;

&lt;p&gt;Bring up the tree view by first clicking on the hamburger menu, and then the 'Tree view' node.&lt;br&gt;
You can close the hamburger menu now if you want more space, the tree view will remain on screen.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--colPV6d5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x2glmqut8e6062i5aept.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--colPV6d5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x2glmqut8e6062i5aept.png" alt="9 tree view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Expand the 'DataTable' node, and delete the fields you don't want (I'm only leaving the sales order number column at this point)&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7ui6QE-u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q07jf5b2hae7loz4ufx6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7ui6QE-u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q07jf5b2hae7loz4ufx6.png" alt="10 Delete Fields"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To add the fields you want, select the 'DataTable' in the tree view, then select 'Edit fields' on the properties pane on the right:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DNyv2Hf---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qn3cw8wb2riwunm2fyqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DNyv2Hf---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qn3cw8wb2riwunm2fyqw.png" alt="11 add fields"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the pane that comes up you can select the fields you need. For now, add the product name and number, and the quantity:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UqkpfBc2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3o6rsqdip74r7v5fj94m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UqkpfBc2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3o6rsqdip74r7v5fj94m.png" alt="12 add fields 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xHVzfklC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0edvz5pe3n9a1mg9j5wo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xHVzfklC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0edvz5pe3n9a1mg9j5wo.png" alt="13 add fields 3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have our very basic app.&lt;/p&gt;
&lt;h1&gt;
  
  
  Filtering the rows
&lt;/h1&gt;

&lt;p&gt;As it sits now, the app now shows ALL sales Order lines. &lt;br&gt;
When we call the app from F&amp;amp;O, we only want to show the lines for the selected order.&lt;br&gt;
We need to implement some logic that filters the rows.&lt;br&gt;
This section has info on that:&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/fin-ops/get-started/embed-power-apps#building-a-canvas-app-that-uses-data-that-is-sent-from-finance-and-operations-apps"&gt;https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/fin-ops/get-started/embed-power-apps#building-a-canvas-app-that-uses-data-that-is-sent-from-finance-and-operations-apps&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we add the app to F&amp;amp;O, we can specify which field is going to be passed to the app when the app is started from F&amp;amp;O.&lt;br&gt;
The framework will put this value in a parameter called 'EntityId'.&lt;br&gt;
Parameter 'cmp' is passed with the Legal Entity value.&lt;br&gt;
When the app starts we want to use that parameter, and put it in a variable so we can filter the records using that variable.&lt;br&gt;
For our scenario, that will be the sales order number.&lt;/p&gt;

&lt;p&gt;First step for this is to put the parameter in a variable.&lt;br&gt;
Sample code for that is in the article linked above, so let's implement this (with a small change).&lt;/p&gt;

&lt;p&gt;In the tree view, select the 'App' node.&lt;br&gt;
Make sure that the 'OnStart' event is selected in the top left.&lt;br&gt;
Expand the formula section so we have more room to put the code.&lt;br&gt;
Then enter the code snippet below. Note that variable names are case sensitive.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If(!IsBlank(Param("EntityId")), Set(FinOpsInput, Param("EntityId")), Set(FinOpsInput, "EMPTY"));
If(!IsBlank(Param("cmp")), Set(FinOpsInput, Param("cmp")), Set(FinOpsLegalEntity, ""));
Notify("EntityId parameter: " &amp;amp; FinOpsInput);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SOVCZEKp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vozfu6iy0gvjgzvn45m7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SOVCZEKp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vozfu6iy0gvjgzvn45m7.png" alt="14 startup code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TIP:&lt;/em&gt; For testing/debugging it is useful to provide some output when the app is called. That's why we are putting the 'Notify' command in the code, so we can verify that the proper value is passed from F&amp;amp;O.&lt;/p&gt;

&lt;p&gt;The next step is to actually filter the content in the view, using the new 'EntityId' variable.&lt;br&gt;
Click on the DataTable in the tree view, and enter the code below in the formula window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Filter(CDSSalesOrderLinesV2,'Sales order (SalesOrderNumber)' = FinOpsInput)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G_Sm7Dxr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3oshh89ao8n4idzupoue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G_Sm7Dxr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3oshh89ao8n4idzupoue.png" alt="15 filter code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You have probably noticed that annoying red 'X' shown in the table view. I think this is due to the naming of the sales order field on the entity. It makes the code generate an incorrect field name.&lt;br&gt;
To further investigate and fix, click on the down-arrow next to the error, and select 'Get help for this error':&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bmEuHjQM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/54dvwm815dklxdhsax63.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bmEuHjQM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/54dvwm815dklxdhsax63.png" alt="16 error help"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It tells us that it does not like the Sales Order field in the grid:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d5XMqf4e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pah5d7bfojdxaymumi2c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d5XMqf4e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pah5d7bfojdxaymumi2c.png" alt="17 error help 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click in the 'Text' field and delete everything so only 'ThisItem' is left.&lt;br&gt;
Then enter a period, and the field list will pop up.&lt;br&gt;
If you scroll down, then you'll find that the field name is NOT just 'Sales Order', but actually&lt;br&gt;
'Sales order (SalesOrderNumber)'&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2589V3hl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1b6xxpt18279h0manyag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2589V3hl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1b6xxpt18279h0manyag.png" alt="18 error fix"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just select that one and the error will go away.&lt;/p&gt;

&lt;p&gt;That should be it for our app. Hit CTRL-S to save it again.&lt;/p&gt;

&lt;p&gt;In order to use the app in F&amp;amp;O, we first need to publish it.&lt;br&gt;
Easy enough, just click 'File' in the top left, and hit the big 'Publish' button.&lt;/p&gt;

&lt;p&gt;We will need the App's ID in order to add it to F&amp;amp;O.&lt;br&gt;
Close the App Editor tab to get back to the main PowerApps site.&lt;br&gt;
Select your new app from the list, and then click 'Details':&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t04ggBLn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zgw47nw97tc0brjxbtt3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t04ggBLn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zgw47nw97tc0brjxbtt3.png" alt="19 app id 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the App ID from the details page, we'll need that in the next step:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pLnLP2RZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ycleuvux336bn9r2kst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pLnLP2RZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ycleuvux336bn9r2kst.png" alt="20 app id 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Add the App to F&amp;amp;O
&lt;/h1&gt;

&lt;p&gt;Now let's add the app to F&amp;amp;O.&lt;br&gt;
As outlined at the top we want to be able to call this from the 'All Sales Orders' screen, so let's open that up, and click on the "PowerApps" button, then 'Add an app':&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gUG7wOG_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/au0sozy10o4hk4rn2mn9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gUG7wOG_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/au0sozy10o4hk4rn2mn9.png" alt="21 fo add app 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the window that pops up, enter a name for the app, your AppID that you copied above, and select the sales order number as the key to be passed to the App:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sUisNw2P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ieu1qp5huyecljmnnmf4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sUisNw2P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ieu1qp5huyecljmnnmf4.png" alt="22 fo add app 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click 'insert' and hit F5 to reload the page.&lt;/p&gt;

&lt;p&gt;When the page reloads you should now see your app under the 'PowerApps' button in F&amp;amp;O:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--40S35_yq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x1qg5ev1pdayo6xedfbv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--40S35_yq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x1qg5ev1pdayo6xedfbv.png" alt="23 fo app added"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To test it, first select a sales order from the grid, then click the PowerApps button and select your app.&lt;br&gt;
If everything went well, it should show the sales ID in the notification and the sales lines in the grid:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jKwmi0LP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/em88xh1dg8lxs0wr60iu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jKwmi0LP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/em88xh1dg8lxs0wr60iu.png" alt="24 fo test"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Tips
&lt;/h1&gt;

&lt;p&gt;Couple tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you are making changes to the app, make sure to publish the app before testing.&lt;/li&gt;
&lt;li&gt;Sometimes it is hard to know if the updated app is executed or not. I usually change something simple, like the text in a header  to make sure that the latest version is executed.&lt;/li&gt;
&lt;li&gt;If you want to remove the app from F&amp;amp;O, or edit the F&amp;amp;O settings, right-click on the PowerApps button and select 'Personalize: PowerApps'.
This will bring up a screen where you can edit or delete (remove) the app:
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ie1ooetB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5qo6mnna7t4z02bd7e0z.png" alt="25 fo edit app"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is also a way to embed a PowerApp into the F&amp;amp;O UI directly via F&amp;amp;O development. See &lt;a href="https://dev.to/robvanb/d365-f-o-and-powerapps-2-27eb"&gt;part 2&lt;/a&gt; for details on that.&lt;/p&gt;

&lt;p&gt;Hope this was useful.&lt;br&gt;
Rob&lt;/p&gt;

</description>
      <category>dynamics365</category>
      <category>d365</category>
      <category>dynamics</category>
      <category>powerapps</category>
    </item>
    <item>
      <title>D365 F&amp;O / PowerBI overview</title>
      <dc:creator>Rob vanBrandenburg</dc:creator>
      <pubDate>Mon, 19 Apr 2021 11:12:58 +0000</pubDate>
      <link>https://dev.to/robvanb/d365-f-o-powerbi-overview-16j</link>
      <guid>https://dev.to/robvanb/d365-f-o-powerbi-overview-16j</guid>
      <description>&lt;h1&gt;
  
  
  D365 F&amp;amp;O / PowerBI overview
&lt;/h1&gt;

&lt;p&gt;‘Microsoft Dynamics 365 for Finance and Operations’ (“F&amp;amp;O” to us mere mortals) has some nice features to do reporting with PowerBI.&lt;br&gt;
However, I’ve found the options, requirements and possible deployments extremely confusing.&lt;/p&gt;

&lt;p&gt;This article tries to summarize the whole ‘ecosystem’ (always wanted to use that word) – and explain what is what.&lt;/p&gt;

&lt;p&gt;Special thanks go to Tom Higginbotham at Microsoft for answering my relentless stream of questions and providing extremely useful guidance.&lt;/p&gt;

&lt;p&gt;The info might be a bit haphazard, and I might revise it several times, but we have to start somewhere, right ?&lt;/p&gt;

&lt;p&gt;Here we go:&lt;/p&gt;

&lt;h2&gt;
  
  
  Tier 1 vs Tier 2 servers
&lt;/h2&gt;

&lt;p&gt;There was a lot of confusion (on my part) to determine if a tier 1 (‘OneBox’) or tier 2 (Test/Sandbox) environment was required.&lt;/p&gt;

&lt;p&gt;This document explains the tier-1 / tier-2 issue:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/analytics/power-bi-embedded-integration?toc=/fin-and-ops/toc.json" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/analytics/power-bi-embedded-integration?toc=/fin-and-ops/toc.json&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some specifics from the doc:&lt;br&gt;
&lt;em&gt;The Power BI Embedded service is automatically deployed and configured for all cloud-hosted, multi-box deployments. Because the service relies on Microsoft Azure services, application analytical workspaces and reports are unavailable in one-box environments.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Microsoft Dynamics 365 team is working on a solution that will enable analytical workspaces in one-box environments without requiring that customers host their own instance of the Power BI Embedded service RvB: they are referring to the setup with a separate Azure DB to host the Entity Store (AXDW)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Can I customize the Power BI embedded reports?&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Yes. To customize the Power BI embedded reports, just install Power BI Desktop in a one-box environment, and follow the steps in Author and distribute Power BI reports with Entity store.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  PowerBI ‘Integration’ vs ‘Embedded’ PowerBI’
&lt;/h2&gt;

&lt;p&gt;There are 2 ways to use PowerBI with F&amp;amp;O – you can mix and match these 2 methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;PowerBI integration :&lt;br&gt;
This is where you link F&amp;amp;O to your PowerBI subscription. This is setup through System Admin -&amp;gt; Setup -&amp;gt; PowerBI.com Integration.&lt;br&gt;
This allows you to add reports/tiles/dashboards from PowerBI.com to Analytical workspaces.&lt;br&gt;
When an existing report on PowerBI.com is “integrated” into D365F&amp;amp;O, it is done so from one of the 3 options on a Workspace:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbjzaye96solgrma5qcht.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbjzaye96solgrma5qcht.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These reports can contain both F&amp;amp;O data and other data sources (EntityStore / DataLake)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; DataSource on report will need to be manually changed when deployed to TEST or PROD environmentThe ‘Open Report Catalog’ and ‘Open Dashboard Catalog’ will add the respective items as Links to the Links list on the right-hand side of the Workspace. Example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7pg2gcy9gz137os5cqw9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7pg2gcy9gz137os5cqw9.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"Open Tile Catalog" will show the list of tiles from Dashboards on PowerBI.com and add them to the designated pane on the Workspace.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Embedded PowerBI :
&lt;a href="https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/analytics/add-analytics-tab-workspaces" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/analytics/add-analytics-tab-workspaces&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Snippet from the above article:&lt;br&gt;
&lt;em&gt;Prerequisites:&lt;/em&gt;&lt;br&gt;
&lt;em&gt;An analytical report (.pbix file) that was created by using Microsoft Power BI Desktop, and that has a data model that is sourced from the Entity store database.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This will require you (the developer) to add an ‘analytics’ tab to an existing (or new) workspace – much like the standard analytics tabs that contain PowerBI reports.&lt;br&gt;
Since a prerequisite for PowerBI Embedded reports is to use the Entity Store, these can only contain F&amp;amp;O data.&lt;/p&gt;

&lt;p&gt;A Tier 2 (or Higher) environment may not necessarily have the embedded Power BI components activated by default. To have it activated requires the submission of a Service Request in LCS as an “Other” request type. This is noted in the following: &lt;a href="https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/lifecycle-services/submit-request-dynamics-service-engineering-team?toc=/fin-and-ops/toc.json#create-service-requests" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/lifecycle-services/submit-request-dynamics-service-engineering-team?toc=/fin-and-ops/toc.json#create-service-requests&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down in the article a bit and you will see as the last point under Other request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxlovh6z2sr5cv8muno1p.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxlovh6z2sr5cv8muno1p.jpg" alt="Alt Text"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Microsoft has rolled out the ability for a user to edit an &lt;strong&gt;embedded&lt;/strong&gt; Power BI report within the F&amp;amp;O browser client. When the user has an embedded Power BI report displayed, there’s the following option:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fot41q0da3n8pvepc3glr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fot41q0da3n8pvepc3glr.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This feature is described here: &lt;a href="https://docs.microsoft.com/en-us/business-applications-release-notes/October18/dynamics365-finance-operations/edit-analytical-workspaces" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/business-applications-release-notes/October18/dynamics365-finance-operations/edit-analytical-workspaces&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;When this is selected, the Power BI editing experience is turned on:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgc65rkfp4xygvhep1ajt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgc65rkfp4xygvhep1ajt.jpg" alt="Alt Text"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Again, this is only for the &lt;strong&gt;embedded&lt;/strong&gt; Power BI reports. While these are PBIX resource files in Visual Studio, once deployed they are sourced on the Power BI Embedded Service (within the F&amp;amp;O subscription).&lt;/p&gt;

&lt;p&gt;An embedded Power BI report can either be a Tab on a Workspace, such as this one in the Fixed Asset Management workspace:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfb39ey3w6zv1u4u0uc3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfb39ey3w6zv1u4u0uc3.jpg" alt="Alt Text"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Or, it can be an entire Workspace, such as CFO Overview/Financial Insights:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6wvoqljogvzugxfhczvq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6wvoqljogvzugxfhczvq.jpg" alt="Alt Text"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Or, it is a Form that is loaded via a menu item, such as Procurement and Sourcing &amp;gt; Inquiries and Reports &amp;gt; Purchase Performance &amp;gt; Purchase and Spend Analysis:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0gaap71g1frjbhndtwg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0gaap71g1frjbhndtwg.jpg" alt="Alt Text"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;These would be the UI options should a new/custom Analytical Report be created, in a Tier 1 Sandbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Embedded PowerBI&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No additional license needed&lt;/li&gt;
&lt;li&gt;Can only contain D365FO data (Entity Store)&lt;/li&gt;
&lt;li&gt;Ability to drill down to D365FO screens&lt;/li&gt;
&lt;li&gt;Requires F&amp;amp;O development / code deployment (but can be edited from UI in future release)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;PowerBI via link or ‘Report Catalog’&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pulls from PowerBI service&lt;/li&gt;
&lt;li&gt;Requires additional PowerBi license&lt;/li&gt;
&lt;li&gt;Cannot drill down to F&amp;amp;O screens&lt;/li&gt;
&lt;li&gt;Can contain D365FO &lt;em&gt;and&lt;/em&gt; external data&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In order to develop the “PowerBi Embedded“ reports, you need a tier 1 environment (probably 1 per developer, like any other F&amp;amp;O development task)&lt;/p&gt;

&lt;p&gt;in order to deploy and run/test the reports (by an end-user) – you will need a Tier 2 environment. (so you could use any tier 2 TEST/UAT environment for this).&lt;/p&gt;

</description>
      <category>dynamics365</category>
      <category>d365</category>
      <category>dynamics</category>
      <category>powerbi</category>
    </item>
    <item>
      <title>Dynamics 365 (E-)Commerce development Proof of Concept (1)</title>
      <dc:creator>Rob vanBrandenburg</dc:creator>
      <pubDate>Thu, 15 Apr 2021 13:45:43 +0000</pubDate>
      <link>https://dev.to/robvanb/dynamics-365-e-commerce-development-proof-of-concept-1d05</link>
      <guid>https://dev.to/robvanb/dynamics-365-e-commerce-development-proof-of-concept-1d05</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/robvanb/dynamics-365-e-commerce-development-proof-of-concept-2-50k0"&gt;Part 2&lt;/a&gt; now available.&lt;/p&gt;

&lt;h1&gt;
  
  
  Intro.
&lt;/h1&gt;

&lt;p&gt;Microsoft has now a full-blown web store front end. In the ever-changing and ever confusing product naming this is currently called Dynamics 365 Ecommerce, which is part of Dynamics 365 Commerce.&lt;br&gt;
Dynamics 365 Commerce was formerly known as D365 Retail, which was formerly part of D365 Finance and Operations, which was formerly known as Dynamics AX. Confused yet? Join the club.&lt;/p&gt;

&lt;p&gt;Ok, done with my usual MS product naming complaint, let’s get down to business.&lt;/p&gt;

&lt;p&gt;In this article I’ll use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;‘D365F&amp;amp;O’ or ‘F&amp;amp;O’ for the ‘backend’ ERP system. Also referred to (in retail/commerce context) as ‘HQ’&lt;/li&gt;
&lt;li&gt;For the website/shop components I’ll use ‘Ecommerce’ or ‘Ecom’&lt;/li&gt;
&lt;li&gt;When referring to the retail development components around retail server, Commerce Scale Unit, POS, etc, I’ll use ‘RetailSDK’.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll try to keep it consistent to keep confusion to a minimum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; All the D365F&amp;amp;O and RetailSDK development (i.e. the CRT extension) was done with Visual Studio 2017.&lt;br&gt;
The Ecom development was done with Visual Studio Code.&lt;/p&gt;

&lt;p&gt;MS actually has some good documentation available on the architecture of the products, so I won’t get into that. However, it is not always clear on how all these pieces fit together.&lt;/p&gt;

&lt;p&gt;In order to educate myself, and also to try out a request from a customer, I decided to see if I can complete this requirement:&lt;/p&gt;

&lt;p&gt;“When a user adds an item to a cart on the Ecom site, the app should check if the item is marked as a warranty item. If it does, it should show a popup.”&lt;/p&gt;

&lt;p&gt;Seems fairly straightforward, yes?&lt;/p&gt;
&lt;h2&gt;
  
  
  Steps and components to modify.
&lt;/h2&gt;

&lt;p&gt;The following steps need to be taken to build this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
D365F&amp;amp;O backend (HQ) development

&lt;ul&gt;
&lt;li&gt;Add ‘warranty’ field to InventTable&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
D365 Commerce Data Exchange (CDX) development 

&lt;ul&gt;
&lt;li&gt;Add field to channel DB&lt;/li&gt;
&lt;li&gt;Add field to CDX process that takes data from the D365 HQ to the channel DB&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
D365 Commerce / RetailSDK development

&lt;ul&gt;
&lt;li&gt;Extend CRT: Expose new field to CRT API (Commerce Run Time)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
D365 Ecom development

&lt;ul&gt;
&lt;li&gt;Surface new field to Ecom site. (To keep things ‘simple’ I initially just create a new module and see if I can get to the field value) &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;
  
  
  &lt;a&gt;1. D365F&amp;amp;O backend (HQ) development&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;This is super simple. Just extend the InventTable, and add the field to it. I created a new EDT that extends the YesNo Enum and added it as a new field to the extended table: &lt;/p&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AquJZDF6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/85ndkr4n4hmgcawjf90n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AquJZDF6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/85ndkr4n4hmgcawjf90n.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;a&gt;2. D365 Commerce Data Exchange (CDX) development&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Here we implement the logic that is going to take the new field (and its value) and copy that to the channel DB. (This is the DB that POS/Ecom uses).&lt;br&gt;
I used this doc for guidance:&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/dynamics365/commerce/dev-itpro/cdx-extensibility#cdx-sample---pull-new-columns-to-an-existing-table"&gt;https://docs.microsoft.com/en-us/dynamics365/commerce/dev-itpro/cdx-extensibility#cdx-sample---pull-new-columns-to-an-existing-table&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First we need to create a resource file that is going to add our field to an existing Retail Scheduler Job.&lt;br&gt;
Standard F&amp;amp;O has a job ‘1040’ which handles products, and has InventTable in it, so it makes sense to add it there:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X1HeqCsn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/msd2l77g8muap86oshpg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X1HeqCsn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/msd2l77g8muap86oshpg.png" alt="Alt Text"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Then we need to Subscribe to the ‘registerCDXSeedDataExtension’ delegate (it’s all in the link above): &lt;/p&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ixveto9g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sajtgyjq8lqm542n17ns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ixveto9g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sajtgyjq8lqm542n17ns.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We build the project, and then run ‘Initialize commerce scheduler’ (Delete configuration = ‘yes’) in F&amp;amp;O.&lt;br&gt;
When done, check the subjob:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DIg_L6Oz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9i9ibrggc7apzqqoy8hy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DIg_L6Oz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9i9ibrggc7apzqqoy8hy.png" alt="Alt Text"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  Extend Channel DB
&lt;/h2&gt;

&lt;p&gt;Now that we have all that setup, we need to create the field in the Channel DB, so that the CDX has a spot to save the data.  Details can be found here: &lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/dynamics365/commerce/dev-itpro/channel-db-extensions"&gt;https://docs.microsoft.com/en-us/dynamics365/commerce/dev-itpro/channel-db-extensions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The way it works is that we need to create a table in the [ext] schema in the Channel DB with the same name as the table we are extending (InventTable), and the same primary index.&lt;/p&gt;

&lt;p&gt;You will need to write an SQL query that does this for you. The easiest way to do this is to find the table you want to extend in the AX schema using SQL Server Management Studio. Then right-click on the table and select 'Script table as' -&amp;gt; 'CREATE To' -&amp;gt; New Query Editor window.&lt;br&gt;
In the new query window you edit the query to only use the [EXT] Schema instead of [AX], then remove all fields except the key fields used in the primary index, and add your extension field(s):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="cm"&gt;/****** Object:  Table [ext].[INVENTTABLE]    Script Date: 3/25/2021 11:42:05 AM ******/&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;ANSI_NULLS&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt;
&lt;span class="k"&gt;GO&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;QUOTED_IDENTIFIER&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt;
&lt;span class="k"&gt;GO&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;INVENTTABLE&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RECID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;bigint&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ITEMID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;nvarchar&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ITKISWARRANTY&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DATAAREAID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;nvarchar&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ROWVERSION&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;I_ITKINVENTTABLEEXTENSION_PRIMKEY&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;CLUSTERED&lt;/span&gt; 
&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ITEMID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;ASC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DATAAREAID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;ASC&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PAD_INDEX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;OFF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;STATISTICS_NORECOMPUTE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;OFF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IGNORE_DUP_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;OFF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ALLOW_ROW_LOCKS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ALLOW_PAGE_LOCKS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;GO&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;INVENTTABLE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt;  &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DF_INVENTTABLE_ITEMID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ITEMID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;GO&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;INVENTTABLE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DataSyncUsersRole&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;GO&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;INVENTTABLE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DataSyncUsersRole&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;GO&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;INVENTTABLE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DataSyncUsersRole&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;GO&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;INVENTTABLE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DataSyncUsersRole&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;GO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deployment of extended table script.
&lt;/h2&gt;

&lt;p&gt;I have not tested the deployment (yet) in a tier 2 environment, but the script needs to be part of your deployable package. See here:&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/dynamics365/commerce/dev-itpro/retail-sdk/retail-sdk-packaging#database-scripts"&gt;https://docs.microsoft.com/en-us/dynamics365/commerce/dev-itpro/retail-sdk/retail-sdk-packaging#database-scripts&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;a&gt;3. D365 Commerce / RetailSDK development&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Now that we have our field in the Channel DB, we need to expose it in the CRT API.&lt;br&gt;
I used this scenario as an example:&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/dynamics365/commerce/dev-itpro/commerce-runtime-extensibility#scenario"&gt;https://docs.microsoft.com/en-us/dynamics365/commerce/dev-itpro/commerce-runtime-extensibility#scenario&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where things get complicated and I spent a LOT of time trying to figure it out.&lt;/p&gt;

&lt;p&gt;In short: Ecom calls the retail API (hosted on the Retail server, which is part of the Scale Unit).&lt;br&gt;
The Retail API basically is just a pass-through to the CRT API.&lt;br&gt;
The key thing is that you need to know what CRT API is called for the process you want to modify.&lt;/p&gt;

&lt;p&gt;For example, when product data is read from the Channel DB before it is added to your cart, that’s what we need to extend, as that is where we need to ‘add’ our new field.&lt;br&gt;
I don’t think there is a direct relation or documentation that explains that  Ecom Data Action ‘A’ calls which Retail API ‘B’, which calls CRT API ‘C’.&lt;/p&gt;

&lt;p&gt;To keep things simple I just started with the Ecom ‘SimpleProduct’ action, and through trial and error (and checking the Commerce Server Event log), I figured out that it called the CRT ‘GetProductsDataRequest’ API.&lt;br&gt;
So that means that I should add a post-trigger to the CRT ‘GetProductsDataRequest’ API.&lt;/p&gt;

&lt;p&gt;The code below is by no means ‘production ready’, it is just POC code to test this out. If you have any remarks/corrections, then please comment below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tip&lt;/strong&gt;: In order to have your request trigger executed, you need to copy the compiled DLL to your retailservers' 'ext' folder ('K:\RetailServer\WebRoot\bin\Ext' in my case), and add the name of the DLL to the 'CommerceRuntime.Ext.config' file in the same directory. Then restart IIS to make sure the new DLL gets picked up.&lt;/p&gt;

&lt;p&gt;What we are doing is that when the standard API has collected the product data, we implement a ‘post’ trigger that uses the retrieved ItemId to get the record from our extension table.&lt;br&gt;
Once found, the result is added to the response as an ‘extension property’:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Dynamics.Commerce.Runtime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Dynamics.Commerce.Runtime.Data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Dynamics.Commerce.Runtime.DataModel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Dynamics.Commerce.Runtime.Messages&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Dynamics.Commerce.Runtime.DataServices.Messages&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;ITK.Commerce.Runtime.GetProductsExtended&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;/// Class that implements a post trigger for the GetProductsDataRequest request type.&lt;/span&gt;
    &lt;span class="c1"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ITKGetProductsDataRequestTrigger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequestTriggerAsync&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;/// Gets the supported request for this trigger&lt;/span&gt;
        &lt;span class="c1"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SupportedRequestTypes&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;get&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetProductsDataRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;OnExecuted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ThrowIf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;ThrowIf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"response"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;EntityDataServiceResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SimpleProduct&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;EntityDataServiceResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SimpleProduct&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

            &lt;span class="n"&gt;SimpleProduct&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PagedEntityCollection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SqlPagedQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QueryResultSettings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SingleRecord&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;DatabaseSchema&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Select&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ColumnSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"ITKISWARRANTY"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
                &lt;span class="n"&gt;From&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"INVENTTABLE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Where&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ITEMID = @itemId AND DATAAREAID = @dataAreaId"&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parameters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"@itemId"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ItemId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parameters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"@dataAreaId"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetChannelConfiguration&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;InventLocationDataAreaId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;dataBaseContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DatabaseContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestContext&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;extensionResponse&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;dataBaseContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadEntityAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ExtensionsEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;ExtensionsEntity&lt;/span&gt; &lt;span class="n"&gt;extensions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extensionResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;itkIsWarranty&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extensions&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ITKISWARRANTY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;itkIsWarranty&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ITKISWARRANTY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;itkIsWarranty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;/// Pre trigger code.&lt;/span&gt;
        &lt;span class="c1"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;/// &amp;lt;param name="request"&amp;gt;The request.&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;OnExecuting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Stub only to handle async signature.&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I spent a lot of time trying to figure out if I now needed to extend the Retail Server API, as the documentation states that the Retail Server API calls CRT. &lt;br&gt;
I’ll save you all the things I tried and looked into: it’s not needed. &lt;br&gt;
The retail server API will ‘automagically’ expose the new field. (Through the extension properties framework – recall that we added the field value as a property to the response in the ‘post’ trigger above).&lt;/p&gt;

&lt;p&gt;To make sure this all worked, and without having to worry about anything related to Ecom, I decided to create a console app that calls the retail API to make sure my new field is being returned.&lt;br&gt;
See here: &lt;a href="https://docs.microsoft.com/en-us/dynamics365/commerce/dev-itpro/consume-retail-server-api"&gt;https://docs.microsoft.com/en-us/dynamics365/commerce/dev-itpro/consume-retail-server-api&lt;/a&gt;&lt;br&gt;
And more specifically here (don’t skip the previous link though – you need those steps): &lt;a href="https://docs.microsoft.com/en-us/dynamics365/commerce/dev-itpro/consume-retail-server-api#access-the-retail-server-apis-by-using-a-console-application"&gt;https://docs.microsoft.com/en-us/dynamics365/commerce/dev-itpro/consume-retail-server-api#access-the-retail-server-apis-by-using-a-console-application&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There was also a section in the documentation that said that we needed to (re)generate TypeScript Proxies. However, for this scenario that is not required, since we only extended an existing API.&lt;br&gt;
If you create a &lt;strong&gt;new&lt;/strong&gt; crt API, then you also need to create a new Retail API to call your CRT API, and you need to generate the proxies.&lt;/p&gt;

&lt;p&gt;Code for the console app below. The parts that are commented out can be used if you extend the ‘GetProductPartsDataRequest’ API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Dynamics.Commerce.RetailProxy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Dynamics.Commerce.RetailProxy.Authentication&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.IdentityModel.Clients.ActiveDirectory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Configuration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;ITKCommerceConsApp&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ITKCallRetailApi&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Uri&lt;/span&gt; &lt;span class="n"&gt;retailServerUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;operatingUnitNumber&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Uri&lt;/span&gt; &lt;span class="n"&gt;authority&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GetConfiguration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;clientId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConfigurationManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppSettings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"aadClientId"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="n"&gt;clientSecret&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConfigurationManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppSettings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"aadClientSecret"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="n"&gt;authority&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ConfigurationManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppSettings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"aadAuthority"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="n"&gt;retailServerUrl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ConfigurationManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppSettings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"retailServerUrl"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="n"&gt;operatingUnitNumber&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConfigurationManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppSettings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"operatingUnitNumber"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConfigurationManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppSettings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"resource"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ManagerFactory&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;CreateManagerFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IdentityModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ActiveDirectory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AuthenticationContext&lt;/span&gt; &lt;span class="n"&gt;authenticationContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IdentityModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ActiveDirectory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AuthenticationContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authority&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;AuthenticationResult&lt;/span&gt; &lt;span class="n"&gt;authResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;authResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;authenticationContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AcquireTokenAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                                        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ClientCredential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="n"&gt;ClientCredentialsToken&lt;/span&gt; &lt;span class="n"&gt;clientCredentialsToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ClientCredentialsToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AccessToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;RetailServerContext&lt;/span&gt; &lt;span class="n"&gt;retailServerContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RetailServerContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;retailServerUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                                          &lt;span class="n"&gt;operatingUnitNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                                          &lt;span class="n"&gt;clientCredentialsToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;ManagerFactory&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ManagerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;retailServerContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dynamics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commerce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RetailProxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PagedResult&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SalesOrder&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ITKGetOrderHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;QueryResultSettings&lt;/span&gt; &lt;span class="n"&gt;querySettings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;QueryResultSettings&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Paging&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PagingInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Top&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Skip&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="n"&gt;ManagerFactory&lt;/span&gt; &lt;span class="n"&gt;managerFactory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;CreateManagerFactory&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;ICustomerManager&lt;/span&gt; &lt;span class="n"&gt;customerManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;managerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetManager&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ICustomerManager&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;customerManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetOrderHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;querySettings&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dynamics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commerce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RetailProxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PagedResult&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SimpleProduct&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nf"&gt;ITKGetProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;productRecId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;QueryResultSettings&lt;/span&gt; &lt;span class="n"&gt;querySettings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;QueryResultSettings&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Paging&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PagingInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Top&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Skip&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="n"&gt;ManagerFactory&lt;/span&gt; &lt;span class="n"&gt;managerFactory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;CreateManagerFactory&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;IProductManager&lt;/span&gt; &lt;span class="n"&gt;productManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;managerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetManager&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IProductManager&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

            &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;productIds&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;productIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;productRecId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

            &lt;span class="c1"&gt;// 68719478279 is he recid of the channel I'm using for testing (Fabrikam Online Store)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;productManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetByIds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;68719478279&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;productIds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;querySettings&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


            &lt;span class="c1"&gt;// Code below is working when using a CRT trigger extension for GetProductPartsDataRequest&lt;/span&gt;
            &lt;span class="cm"&gt;/*
            QueryResultSettings querySettings = new QueryResultSettings
            {
                Paging = new PagingInfo() { Top = 10, Skip = 0 }
            };

            ProductLookupClause productLookupClause = new ProductLookupClause();
            productLookupClause.ItemId = productId;

            System.Collections.ObjectModel.ObservableCollection&amp;lt;ProductLookupClause&amp;gt; lookupClauseList = 
                new System.Collections.ObjectModel.ObservableCollection&amp;lt;ProductLookupClause&amp;gt;();

            lookupClauseList.Add(productLookupClause);

            List&amp;lt;IObservable&amp;lt;ProductLookupClause&amp;gt;&amp;gt; productLookupClauseList = new List&amp;lt;IObservable&amp;lt;ProductLookupClause&amp;gt;&amp;gt;();
            productLookupClauseList.Add(productLookupClause as IObservable&amp;lt;ProductLookupClause&amp;gt;);

            ProductSearchCriteria productSearchCriteria = new ProductSearchCriteria();

            productSearchCriteria.ItemIds = lookupClauseList;
            //NOTE: ProjectionDomain/Context is required when calling productManager.Search
            ProjectionDomain projectionDomain = new ProjectionDomain();
            projectionDomain.ChannelId = 68719478278; 
            productSearchCriteria.Context = projectionDomain;

            ManagerFactory managerFactory = await CreateManagerFactory();
            IProductManager productManager = managerFactory.GetManager&amp;lt;IProductManager&amp;gt;();

            return await productManager.Search(productSearchCriteria, querySettings);
            */&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;GetConfiguration&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// Code that is commented out below can be used to call sales order history&lt;/span&gt;
            &lt;span class="cm"&gt;/*
            Microsoft.Dynamics.Commerce.RetailProxy.PagedResult&amp;lt;SalesOrder&amp;gt; orderHistory = Task.Run(async() =&amp;gt; await ITKGetOrderHistory("2001")).Result;
            IEnumerator orderEnum = orderHistory.Results.GetEnumerator();

            while (orderEnum.MoveNext())
            {
                SalesOrder order = orderEnum.Current as SalesOrder;
                Console.WriteLine(order.SalesId);
            }
            */&lt;/span&gt;

            &lt;span class="c1"&gt;// For the Fabrikam Online Store item 91009 is 'Round Oversized Sunglasses"&lt;/span&gt;
            &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dynamics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commerce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RetailProxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PagedResult&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SimpleProduct&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;itkProducts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
                &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;ITKGetProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;68719498121&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//This is the recid of the product in the ECORESPRODUCT table&lt;/span&gt;

            &lt;span class="n"&gt;IEnumerator&lt;/span&gt; &lt;span class="n"&gt;resultEnum&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;itkProducts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetEnumerator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MoveNext&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;SimpleProduct&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resultEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;SimpleProduct&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RecordId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;


            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Press Enter"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  To recap:
&lt;/h2&gt;

&lt;p&gt;The extension executes a separate query to get the referenced record from the '[ext].Inventtable' extension table.&lt;br&gt;
Then the new field(s) get added to the entity that is returned:&lt;/p&gt;

&lt;p&gt;Snippet from the CRT extension class 'ITKGetProductsDataRequestTrigger.cs':&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;itkIsWarranty&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extensions&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ITKISWARRANTY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;itkIsWarranty&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ITKISWARRANTY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;itkIsWarranty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then these can be accessed from the client / caller like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M9mBCrvh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kpe3fkowjm3mu9ivdlb7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M9mBCrvh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kpe3fkowjm3mu9ivdlb7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a&gt;4. D365 Ecom development&lt;/a&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Surface new field to Ecom site.
&lt;/h2&gt;

&lt;p&gt;(To keep things ‘simple’ I initially just create a new module and see if I can get to the field value).&lt;/p&gt;

&lt;p&gt;To get started with this I used Sam Jarawan’s (Microsoft) excellent Ecom development starter guide.&lt;br&gt;
I setup my E-Com development environment and linked it to a ‘regular’ D365F&amp;amp;O Cloud Hosted Environment (CHE). This is just a regular F&amp;amp;O dev box. &lt;br&gt;
The environment does NOT have an E-Com website linked to it, but we don’t need that for our purpose. It does have a retail server, and that’s all we need at the moment. (After all, that’s where we built our CRT extension explained above).&lt;/p&gt;

&lt;p&gt;Follow Sam’s doc to create a new ‘product-feature’ module. For this POC I did the bare minimum, but you can follow along the doc for a good idea on how things stick together.&lt;/p&gt;

&lt;p&gt;In our example above, we extended the ‘GetProductsDataRequest’, which is called by the Ecom ‘get-simple-product’ action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DISCLAIMER:&lt;/strong&gt; the part below is how I currently &lt;em&gt;think&lt;/em&gt; it works, I could be wrong in some of my assumptions, but in the end I had a working POC, so I can’t be all that wrong 😊&lt;/p&gt;

&lt;p&gt;Using the generated/modified ‘product-feature’ module example from the doc mentioned above:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File ‘Product-feature.tsx’:&lt;/strong&gt;&lt;br&gt;
Here we reference ‘productsDataAction’:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ProductFeature&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PureComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IProductFeatureProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IProductFeatureData&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;JSX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;productsDataAction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is executed when we load the module, as this references this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File ‘Product-feature.data.tsx’:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IProductFeatureData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AsyncResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SimpleProduct&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells me that the return object is of type 'SimpleProduct'.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File ‘Product-feature.definition.json’:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"dataActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;    
        &lt;/span&gt;&lt;span class="nl"&gt;"productsDataAction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@msdyn365-commerce-modules/retail-actions/dist/lib/get-simple-products"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"runOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where my 'productDataAction' is mapped to the actual E-Com data action.&lt;br&gt;
Looking at the file referenced in product-feature.definition.json ("@msdyn365-commerce-modules/retail-actions/dist/lib/get-simple-products"):&lt;/p&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RREWVgZ1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ru3pxno1x7k8vr7egm43.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RREWVgZ1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ru3pxno1x7k8vr7egm43.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This led me to find that this called the Retail API with ‘ProductManager.GetByIds’, so to recap the full stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;E-Com DataAction: get-simple-products&lt;/li&gt;
&lt;li&gt;Retail Server API: ProductManager.GetByIds&lt;/li&gt;
&lt;li&gt;CRT: POST Request Trigger GetProductsDataRequest

&lt;ul&gt;
&lt;li&gt;Response = EntityDataServiceResponse&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;br&gt;
Here are the E-Com changes I made to get this to work:&lt;br&gt;
&lt;strong&gt;product-feature.data.ts:&lt;/strong&gt;&lt;br&gt;
Added the data action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AsyncResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SimpleProduct&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@msdyn365-commerce/retail-proxy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IProductFeatureData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AsyncResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SimpleProduct&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Product-feature-definition.json:&lt;/strong&gt;&lt;br&gt;
Reference the data action that I added in 'product-feature.data.ts:'&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"$type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"contentModule"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"friendlyName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"product-feature"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"product-feature"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Custom Product Feature Module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"product-feature"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Additional tags go here"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dataActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;    
        &lt;/span&gt;&lt;span class="nl"&gt;"productsDataAction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@msdyn365-commerce-modules/retail-actions/dist/lib/get-simple-products"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"runOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="nl"&gt;"config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"productTitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"friendlyName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Product Title"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The Product Title"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"productDetails"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"friendlyName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Product Details"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Product Details"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"richText"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"productPrice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"friendlyName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Product Price"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Product Price"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"resourceKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"resource description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"resource value from product-feature.definition.json"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Product-feature.tsx&lt;/strong&gt;&lt;br&gt;
Here we process the data as it comes back from the API call. The interesting stuff happens of course with the warranty field, as that is what we added as a new field. The other fields in here are fields that were already part of this API call.&lt;br&gt;
You can see that the field and value are passed as extension properties, ‘key’ being the field name and ‘value’ being the actual value of the field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IProductFeatureData&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./product-feature.data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IProductFeatureProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./product-feature.props.autogenerated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IProductFeatureViewProps&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;IProductFeatureProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IProductFeatureData&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;productName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;productInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;productPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;productWarranty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 *
 * ProductFeature component
 * @extends {React.PureComponent&amp;lt;IProductFeatureProps&amp;lt;IProductFeatureData&amp;gt;&amp;gt;}
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ProductFeature&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PureComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IProductFeatureProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IProductFeatureData&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;JSX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;productsDataAction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Set default values&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ProductName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productTitle&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productTitle&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No product title defined.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ProductInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productDetails&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productDetails&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No product details defined.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ProductPrice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;130&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ProductWarranty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No Value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// If we get the product details from the retail server, then we use that&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productsDataAction&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;ProductName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;
                    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;
                    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No product data from Retail Server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;ProductInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Description&lt;/span&gt;
                    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Description&lt;/span&gt;
                    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No product data from Retail Server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;ProductPrice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Price&lt;/span&gt;
                    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`$&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
                    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No product data from Retail Server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExtensionProperties&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;ProductWarranty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Result and result properties returned&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExtensionProperties&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExtensionProperties&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ITKISWARRANTY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExtensionProperties&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="nx"&gt;ProductWarranty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productsDataAction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExtensionProperties&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;IntegerValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="nx"&gt;ProductWarranty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Warranty not specified for item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                        &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductFeatureViewProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;productName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;productInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;productPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductPrice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;productWarranty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductWarranty&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;renderView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ProductFeatureViewProps&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ProductFeature&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;product-feature-view.tsx:&lt;/strong&gt;&lt;br&gt;
And finally we modify the view to show our handy work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*!
 * Copyright (c) Microsoft Corporation.
 * All rights reserved. See LICENSE in the project root for license information.
 */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IProductFeatureViewProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./product-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IProductFeatureViewProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'row'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Product Title: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Product Description: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productInfo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Product Price: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productPrice&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Product Warranty: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productWarranty&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have it all setup, let’s see if it works:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i_BTJDNG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oeygp7puj9qbtpkzs0r5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i_BTJDNG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oeygp7puj9qbtpkzs0r5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The nice thing is that due to the way I wrote the code in the 'product-feature.tsx' file, is that right away I know if the data is pulled from the retail server or not.&lt;br&gt;
So now, let’s change the warranty field on our item in F&amp;amp;O (I added it to the UI):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wHwMyCLY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmn5bidjuoxk4qj5k7ze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wHwMyCLY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmn5bidjuoxk4qj5k7ze.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cjw4JNgK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bc7nydajqyq51i3q7os3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cjw4JNgK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bc7nydajqyq51i3q7os3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we run Retail Scheduler Job 1040 (Products) to push the update to the Channel DB, wait until the updates are applied, and then check again:&lt;br&gt;
Success! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; initially the update did not show. I was thinking (hoping) it might be a caching issue, and indeed after I killed and restarted the yarn command, it showed the update:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4XwM26WC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xw45jsejd0rg44qjdy7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4XwM26WC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xw45jsejd0rg44qjdy7r.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is by no means a complete how to, but hopefully it can provide some value. &lt;/p&gt;

</description>
      <category>dynamics365</category>
      <category>d365</category>
      <category>dynamics</category>
      <category>ecommerce</category>
    </item>
  </channel>
</rss>
