Power Apps Portals – ‘Page Not Found’ goes missing

The Power Apps (D365) Portals has a standard ‘Page Not Found’ feature that displays a customisable page when the user navigates to a URL that does not exist.

Page Not Found Page

What do you do if your ‘Page Not Found’ page is not found? I recently encountered this problem in an environment where an incorrect URL was displaying the dreaded 502 Error rather than the ‘Page Not Found’ page.

Portal 502 Error

This is where the Portal Checker in the Power Apps Portal Admin Centre is your friend. Run the Portal Checker and examine the results for the following entries.

Page Not Found Site Marker Configuration

Home Site Marker Configuration

If either of these have a Warning against them, check the respective Site Marker to ensure it is pointing to the correct page. In my case the Home Site Marker had been incorrectly modified and was no longer pointing to the relevant Home page. Having made the adjustment my ‘Page Not Found’ was operational again and incorrect URLs were being sent to the right page.

Power Apps Portals – Login By Email

Power Apps Portals support multiple authentication methods. For external accounts, managed through Contact records in D365, the process of registration used to require the user to provide a separate Username and Email address. Although this is still the default scenario it is now possible to require the user to provide only their email address for sign-in.

To modify the registration process, change the Authentication/Registration/LocalLoginByEmail Site Setting from false to true. No more having the use some crafty JQuery to populate a (hidden) Username field with the content of an email address.

D365 Portals – application/xml

I keep forgetting how to do this and can’t remember where I saw it written down so I am writing this down now. If you need to check the fetchXML that is being called as part of a Web Template then you can return that fetchXML in a Web Page. This can be useful where you have fetchXML that is generated dynamically based on request parameters or if you just want to check the values that are included in your fetchXML from the request.params collection.

  1. Create the Web Template with your fetchXML query
  2. After the {% endfetchxml %} line, display the content of you fetchXML query using the XML property of your fetchXML object.
  3. Set the MIME Type of the Web Template to application/json
  4. Create a Page Template for your Web Template, with no headers or footers.
  5. Create a Page using the Page Template so you can get the XML content

For example, my Web Template would look like this

{% fetchxml assetQuery %}
<fetch version='1.0' output-format='xml-platform' mapping='logical' page='1' count='200'>
  <entity name='msdyn_customerasset' >
    <attribute name='msdyn_customerassetid' />
    <attribute name='msdyn_account' />
    <attribute name='msdyn_parentasset' />
    <attribute name='msdyn_name' />
{% endfetchxml %}

{{ assetQuery.xml }}

D365 Portals : X-Content-Type-Options Header

In an earlier post I provided a few of options for dealing with JavaScript code in your D365 portals. The second of those options was to modify the extension of the file that is attached to the Web File Note so it isn’t blocked as an attachment.

With a recent upgrade to the portal it appears that Microsoft have now closed the door on that particular option and for good (security) reasons. They have now added the X-Content-Type-Options header to the response with a setting of nosniff. This means that when the browser detects a difference between the file extension and the MIME type then the browser generates an error and the script is not loaded.

This means that in order to use custom JavaScript files in your D365 portals you are left with either option #1 or option #3 from my previous post, or use a CDN.

D365 Portals – Custom JS

There are a few ways you can host your custom JavaScript for your D365 portal within the portal configuration.

  1. Circumvent the System Settings and allow JS files to be uploaded to D365. The default system settings disallow JS files from being uploaded to D365. If you remove the JS extension from this list you can upload the files to D365. However, this is not ideal because it exposes your whole environment to malicious JS files potentially being uploaded.
  2. Change the file extension on your JS files. Although D365 won’t allow JS files because of the reason mentioned above, you can change the extension of the file, for example, .AXD. You are now able to attach the file to the Notes in your Web File and you can still give your web file a Partial URL ending in .JS. The JavaScript file will still be accessible as normal through the SCRIPT tag.
  3. My preferred option uses a similar technique to that used to return JSON responses from FetchXML queries in a Web Template. If we enter the JavaScript code directly in a Web Template and set the MIME Type to application/javascript we can use that Web Template in a page, with no header/footer, to serve up our custom JavaScript.
  4. Step 1. Create the Web Template

    Step 2. Create the Page Template with no header/footer

    Step 3. Create the JavaScript ‘Page’

    Step 4. Create the a regular Portal Page and embed the SCRIPT tag to request the custom JavaScript

    The result is that the JavaScript file is served from D365 and the functions run as normal.

    Obviously, if you have access to a CDN then you can upload them to there and add the necessary tags to your portal Pages, Web Templates etc.

D365 Portals – Language agnostic Content Snippets

When dealing with multi-language websites Content Snippets are a great way to separate out your language specific portal content from your Web Templates and Page Copy.

If you want to use a single Content Snippet across all of your portal languages, for example with generic HTML that is language agnostic, then all you need to do is ensure the value in the Content Snippet Language field is left blank.

D365 Portals – Parent Web Links and Authenticated Users

When you need to display a multi-level web link set the parent level web link does not need to have a page defined. However, this means that the parent level web link will always be visible. If the child web links are behind Restrict-Read web pages, then unauthenticated users will always see the parent level menu option, even if they can’t see the children. Although this is not a major issue as the menu item does not go to a page, it can be confusing to the users if they click on the menu item and it doesn’t go anywhere.

To overcome this problem we can assign a blank page to the parent web link using the Blank Page Page Template. The screenshot below shows the configuration for the parent web link page.
Blank Page

After creating the page we create an Access Control Rule (Restrict Read) that is linked to the Authenticated Users Web Role.
Blank Page - Access Control Rule

Having configured the page, all that is left to do is link the page to the Web Link.
Web Link

Now the Parent Web Link is only visible once the user has logged into the portal and not displayed to unauthenticated users.