Skip to content

Instantly share code, notes, and snippets.

@milolav
Last active May 6, 2019 23:34
Approach to making Dynamics 365 CE Reports available in the iPad app.

Making Dynamics 365 CE reports available in UCI on iOS devices

At the time of writing, Microsoft does not officially support running reports in an app on iOS / Android / Windows devices in the Unified Interface (UCI), but as it turns out, it's actually possible to display a report within the app using SiteMap entries pointing to Web Resources.

Reports are just another url in Dynamics and it seems the only reason why is that not working in the app is because every time you click on a item in the reports view it opens it in a new window.

First Idea

The first idea was just to use url of specific report, put it into Site Map like:

/crmreports/viewer/viewer.aspx?action=filter&helpID=User Summary.rdl&id={e5838060-8866-e911-a819-000d3ab29ccc}&appid=3ef28a1b-5666-e911-a9c5-000d3ab78b73

The problem is that menu items with this url do not show in the menu.

Web Resource to the rescue

Second idea was just to create a simple web resource and put in the following code:

<html>
  <body>
    <iframe src="/crmreports/viewer/viewer.aspx?action=filter&helpID=User Summary.rdl&id={e5838060-8866-e911-a819-000d3ab29ccc}" style="height: 100%; width: 100%;" frameborder="0"></iframe>
  </body>
</html>

And that worked!

Since it is not preferable to to have a separate web resource for every report next challenge was to pass data to that web resource. Microsoft provides sample on how to pass data to web resources outlined here:

https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/sample-pass-multiple-values-web-resource-through-data-parameter

What's more interesting, passing data parameter also works in the Site Map. Not through the visual editor in Dynamics, but it does work by directly editing the SiteMap XML or using SiteMap Editor in XRMToolBox. Just adding data parameter after the web resource name like:

$webresource:new_reportwrapper.html?data=mydatavalue1

Which means that report guid value can be passed like this:

$webresource:new_reportwrapper.html?data=e5838060-8866-e911-a819-000d3ab29ccc

And the only thing left is to make use of passed value.

Code

Web Resource:

<html><body style="background: white; position: absolute; margin: 0.5em; top: 0; left: 0; right: 0; bottom: 0;">
<script>
function loadReport() {
  if (location.search != "") {
    params = location.search.substr(1).split("&");
    for (p in params) {
      var kv = params[p].replace(/\+/g, " ").split("=");
      if(kv[0].toLowerCase() === "data") {
        var guid = kv[1];  
        var url = "/crmreports/viewer/viewer.aspx?id=" + guid;
        document.getElementById("report").src = url;
        return;
      }
    }
  }
  document.getElementById("msg").innerHTML = "Report parameters not set!"; 
}

document.onreadystatechange = function () {  
  if (document.readyState == "complete") {  
    document.getElementById("report").onload = function() {
        document.getElementById("loading_overlay").style.display = "none";
    }
    loadReport();  
  }  
}
</script>
<iframe id="report" src="" style="height: 100%; width: 100%;" frameborder="0"></iframe>
<div id="loading_overlay">
<div style="background: none repeat scroll 0 0 black; position: fixed; display: block; opacity: 0.5; left: 0; top: 0; height: 100%; width: 100%;"></div>
<p id="msg" style="position: absolute; top: 50%; left: 50%; transform: translateX(-50%) translateY(-50%);">LOADING ...</p>
</div>
</body>
</html>

Site Map item:

<SubArea
  Id="tempId_636927761987954911"
  Url="$webresource:new_reportwrapper.html?data=e5838060-8866-e911-a819-000d3ab29ccc"
  Title="User Summary Report"
  AvailableOffline="false"
  PassParams="false"
  Client="All"
  Sku="All"
/>

Final result

ipad report

Additional stuff

This approach can also be used for getting diag tool inside the app by creating a web resource with the following code and linking that in the site map.

<html>
  <body>
    <iframe src="/tools/diagnostics/diag.aspx" style="height: 100%; width: 100%;" frameborder="0"></iframe>
  </body>
</html>

Which allows you to access it from within the app rather than typing or pasting this in a browser.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment