ENGINEERED CODE BLOG

Power Apps Portals: fetchxml Liquid Tag and Entity Permissions

The fetchxml Liquid tag is arguably the most powerful Liquid tag in Power Apps Portals – it allows you to meet complex requirements for the display of data. But, if you combine it with a complex Entity Permissions model, you could find yourself getting unexpected errors. In this post I’ll cover what can cause those errors, and how to work around them.

The Situation

Let’s assume you’ve got Entity A which is related to Contact (Contact 1:N Entity A). Then you have Entity B, which is related to Entity A (Entity A 1:N Entity B).

To expose these entities on the Portal, you can create Entity Permissions, with a Contact-scoped Entity Permission on Entity A, and a Parent-Scoped Entity Permission on Entity B. If you use functionality like Entity List and Entity Forms, this should work just fine.

However, if you want to use the fetchxml tag to query data in Entity B, and include filtering based on Entity A using a link-entity, you’ll run into problems. Here is an example of a FetchXML query:

{% fetchxml myquery %}
  <fetch aggregate="true" >​
    <entity name="ec_entityb" >​
      <attribute name="ec_number" alias="numbersum" aggregate="sum" />​
      <filter type="or" >​
        <condition entityname="ec_entitya" attribute="ec_filtertest" operator="eq" value="894820000" />​
        <condition entityname="ec_entitya" attribute="ec_filtertest" operator="eq" value="894820001" />​
      </filter>​
      <link-entity name="ec_entitya" from="ec_entityaid" to="ec_entityaid" />​
    </entity>​
  </fetch>​
{% endfetchxml %}

Which will produce the following error:

Liquid error: Exception has been thrown by the target of an invocation.

The FetchXML is valid – it works in the FetchXML Builder in XrmToolBox. So why doesn’t it work on Power Apps Portals?

The Application of Entity Permissions

In order to make the query as efficient as possible, the Portals code adds to your FetchXML the necessary filters to enforce Entity Permissions. This is as opposed to running the full query, and then performing the security trimming on the results.

The problem in this case is there is a conflict between our FetchXML, and the additional FetchXML added to enforce Entity Permissions.

The good news is, it is possible to look at the complete FetchXML that is sent to the CDS server, including both your FetchXML, and what has been added to enforce Entity Permissions. You can do that by accessing the .xml attribute of your fetchxml object, like so (the code also HTML encodes using the h filter so that it can be displayed on the page):

{{ myquery.xml | h }}

Which yields the following result:

<fetch mapping="logical" aggregate="true">
  <entity name="ec_entityb">
    <attribute name="ec_number" alias="numbersum" aggregate="sum" />
    <filter type="or">
      <condition entityname="ec_entitya" attribute="ec_filtertest" operator="eq" value="894820000" />
      <condition entityname="ec_entitya" attribute="ec_filtertest" operator="eq" value="894820001" />
    </filter>
    <filter type="and">
      <filter type="or" hint="union">
        <condition entityname="generated_alias_ec_entitya_1" attribute="ec_contact" operator="eq" value="aedf70f8-5520-ea11-a811-000d3af421db" />
      </filter>
    </filter>
    <link-entity name="ec_entitya" from="ec_entityaid" to="ec_entityaid" />
    <link-entity name="ec_entitya" from="ec_entityaid" to="ec_entityaid" alias="generated_alias_ec_entitya_1" link-type="outer" />
  </entity>
</fetch>

There you can see that the Portals code is adding another link-entity, which causes confusion with the existing one. You’ll also notice the additional filter, which filters based on a contact with an id of aedf70f8-5520-ea11-a811-000d3af421db, the ID of the currently logged in contact.

The Fix

The error is occurring because the conditions in the original FetchXML query are ambiguous – they refer to Entity A, but there are two possible links to Entity A. To remove the ambiguity, you’ve got two options:

  1. Add your own alias to the your link-entity and your filter.
  2. Once you’ve used the .xml attribute to view the auto-generated alias, remove you own link-entity and use the auto-generated alias in your conditions.

I prefer the first option. The alias that is automatically generated could in theory change at any point, breaking your code. Create your own alias just to be safe. Something like:

{% fetchxml myquery %}
  <fetch aggregate="true" >​
    <entity name="ec_entityb" >​
      <attribute name="ec_number" alias="numbersum" aggregate="sum" />​
      <filter type="or" >​
        <condition entityname="myalias" attribute="ec_filtertest" operator="eq" value="894820000" />​
        <condition entityname="myalias" attribute="ec_filtertest" operator="eq" value="894820001" />​
      </filter>​
      <link-entity name="ec_entitya" from="ec_entityaid" to="ec_entityaid" alias="myalias" />​
    </entity>​
  </fetch>​
{% endfetchxml %}

And with that small change, the query works as expected.

Undocumented fetchxml Tag

Despite being a powerful and popular tag, unfortunately there is no documentation for the fetchxml Liquid tag in the Power Apps Portals documentation. I’ve been told it’s on Microsoft’s list of things to do. If you’re interested, here is a summary of the available options:

{% fetchxml query %}
  <fetch version="1.0" mapping="logical">
    <!-- Write FetchXML here, use Liquid in here if you want, to build XML dynamically. -->
  </fetch>
{% endfetchxml %}
  
{{ query.xml | escape }}
{{ query.results.total_record_count }}
{{ query.results.more_records }}
{{ query.results.paging_cookie | escape }}
{% for result in query.results.entities %}
  {{ result.id | escape }}
{% endfor %}

One response to “Power Apps Portals: fetchxml Liquid Tag and Entity Permissions”

  1. […] post Power Apps Portals: fetchxml Liquid Tag and Entity Permissions appeared first on Engineered […]

Leave a Reply

Your email address will not be published. Required fields are marked *

Contact

Engineered Code is a web application development firm and Microsoft Partner specializing in web portals backed by Dynamics 365 & Power Platform. Led by a professional engineer, our team of technology experts are based in Regina, Saskatchewan, Canada.