The importance of Portal speed is clear for the user experience and should be an obvious priority for any Portal Implementation. Dynamics 365 Online Portal is a great platform to build a customer, employee or partner-facing portal. While working with multiple implementations we always like to focus on page load times. We would like to share a few ideas that we have implemented and have been very effective in keeping page loads as fast as possible.
Enable Footer and Header Cache
- If the customer has placed dynamic content in Header/Footer, then enable Footer and Header Cache.
- Check the below link for changes in Web Templates needed to be made manually after the Site Settings :
https://docs.microsoft.com/en-us/dynamics365/customer-engagement/portals/enable-header-footer-output-caching
Disable Tracking Feature on Web Page and Web File
- Making sure Tracking feature is disabled for both Web Page or Web File
- Check that there are no Web Pages or Web Files using a Yes value in Enable Tracking column (use Advanced Find as helper friend for this):
Be cautious about Entity Permissions
Avoid having ‘Read Only’ Privileges in more than one Entity Permission records for the same Entity. For example, having the below Entity Permission records will slow down ‘Sales Order’ Page Performance.
Entity Permission – Orders – Read Privilege is not Enabled
Entity Permission – Orders Read Only – Read Privilege is not Enabled
Disable Change Tracking on Web Page and Web File entity
- Check that webpagelog and webfilelog entities are not enabled for Change Tracking
- Change Tracking feature is Solutions area – be sure to Save and Publish after changes
Disable Login Tracking
- Make sure that Site Setting LoginTrackingEnabled is either not present or set to false
- This setting is off by default as it is not shipped as part of the out of the box templates only something customer would have added
Avoid showing Lookup fields as Dropdowns in the Portal Form
Avoid showing Lookup fields as ‘Dropdown fields’ for a large set of Data will help us to improve the speed.
- If lookup is a customer lookup field, it will populate all the accounts and contacts, no easy way to just show accounts without doing client-side customization. Which means on the server side it will always load all accounts and contacts on every page load, this adds at least 2-4 seconds on your page load time.
To fix this , We can hide the lookup field, dynamically create a dummy dropdown field and populate it with the required data.
Please find below an example, where we are hiding the ‘Customer’ Lookup field in the form and creating a dummy dropdown field for the same.
Step 1 : Create a Liquid Template query to fetch the Customer Details. Have a look at the below link for details about usage of Liquid Templates in Dynamics 365 Portal.
We used the below liquid-template Fetch XML query to get Customers data.
{% fetchxml userAccounts %}
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">
<entity name="account">
<attribute name="name" />
<attribute name="accountid" />
<attribute name="accountnumber" />
<order attribute="name" descending="false" />
</entity>
</fetch>
{% endfetchxml %}[{% for result in userAccounts.results.entities %}
{ "accountid": "{{result.accountid}}",
"name": "{{result.name}}",
"accountnumber": "{{result.accountnumber}}"
}{% unless forloop.last %},{% endunless %}
{% endfor %}]
Step 2: Create a Dummy Field for the Customer and hide the Original Customer Id field as shown below. Here ‘customerId’ is the Id of Customer Field.
var customerValue = $(customerId).val();
var dummyControlId = "#customerid_dummy";
if ($("#customerid_dummy").length <= 0) {
$(customerId).parent().parent().append('<select name="customerid_dummy" id="customerid_dummy" onchange="Customer_OnChange();" class="lookup form-control"></select>');
$(customerId).hide();
}
$('#customerid_dummy').empty();
$(customerId + "_label").show();
// Hide the Customer Lookup field.
$(customerId).hide();
$(customerId).closest('div .input-group').hide();
Step3 : Set value for the ‘Customer’ Lookup field on ‘OnChange’ event of “Customer_dummy” field.
function Customer_OnChange() {
var customerId = $("#customerid_dummy").val();
//Set value for the Customer Lookup field
$("#customerid").val(customerId);
$("#customerid_name").val($("#customerid_dummy option:selected").text());
$("#customerid_entityname").val('account');
}
Store the data in Session using sessionStorage
Instead of making repeated calls to the server for the same set of Data, we can store it in sessions using sessionStorage
+.
// Save data to sessionStorage
sessionStorage.setItem('key', 'value');
// Get saved data from sessionStorage
var data = sessionStorage.getItem('key');
// Remove saved data from sessionStorage
sessionStorage.removeItem('key');
// Remove all saved data from sessionStorage
sessionStorage.clear();
For example, In our case we need to show ‘Accounts’ details in all the Pages. So we used ‘sessionStorage’ to store Account details and Retrieve values from it.
var response = "<option value=''></option>";
if (!getIsNullOrEmpty(sessionStorage.getItem("AllAccounts"))) {
var accounts = JSON.parse(sessionStorage.getItem("AllAccounts"));
accounts.forEach(function(element) {
response += "<option acctno='" + element.accountnumber + "' value='" + element.accountid + "'>" + element.name + "</option>";
});
$('#customerid_dummy').empty();
$('#customerid_dummy').html(response);
} else {
var url = '/liquid-templates/GetAccountDetailsByContactId/';
$.ajax({
type: "GET",
url: url,
dataType: 'json',
async: false,
success: function(result) {
var accounts = result;
sessionStorage.setItem("AllAccounts", JSON.stringify(accounts));
accounts.forEach(function(element) {
response += "<option acctno='" + element.accountnumber + "' value='" + element.accountid + "'>" + element.name + "</option>";
});
$('#customerid_dummy').empty();
$('#customerid_dummy').html(response);
}
}