ecLearn LMS, developed by Engineered Code, is proud to sponsor Community Summit North America. Visit us at booth #1857 and get on the list for our Summitland Prize!

ENGINEERED CODE BLOG

Adding SharePoint Integration to the Employee Self-Service Portal Without Server-side Code – Part 3

In my third post in the series on how you can add an integration with SharePoint to the Employee Self-Service Portal in Dynamics 365 without using server-side code, I’ll dive into using the SharePoint REST API to display documents in a folder related to a record in Dynamics 365.

SharePoint REST API Basics

If you’re not familiar with SharePoint, there is a bit of a learning curve to using the REST API. However, the documentation is pretty good, and what we’re trying to do in this scenario is basic and only requires a single call to get a list of the files in a particular folder:

http://site url/_api/web/GetFolderByServerRelativeUrl('/Folder Name')/Files

If you’re using the default site, then site url is simply the URL of your SharePoint instance (for example, https://yourcompany.sharepoint.com). However, if you created a different SharePoint site, the URL looks something like https://yourcompany.sharepoint.com/sites/CRM. The good news is that this is exactly what is in the Absolute URL field in the SharePoint Site entity that we obtained in the previous post, and is contained in the sharepointsiteurl Liquid variable.

So, since we have the URL of our SharePoint server, and the folder we’re interested in, we have everything to construct our request to retrieve the list of files – except for authentication.

SharePoint REST API Authentication

The SharePoint REST API requires that we pass an OAuth Bearer token as part of our request for authentication. In a previous blog post, I wrote about getting a SharePoint OAuth token within a Dynamics 365 Web Resource. The good news is, that when we’re logged into a portal using Azure AD, we’re in precisely the same situation, so the same technique applies.

I’m not going to rehash everything from that post, but to get it working we’ll need:

  • Your Azure AD Tenant ID (AKA the Directory ID)
  • The Application ID (AKA the Client ID) for an App Registration within your Azure AD tenant. This App Registration needs to be configured as follows:
    • A Web app/API type application
    • Reply URL should be the URL of your portal (for example, https://yourportal.microsoftcrmportals.com/)
    • Edit the Manifest and set oauth2AllowImplicitFlow to true
    • In Required Permissions, add Office 365 SharePoint Online, and include the Read items in all site collections permission. Don’t forget to click Grant permissions after saving!
  • The base URL for your SharePoint server (without the path for any SharePoint Sites) – for example https://yourcompany.sharepoint.com, not https://yourcompany.sharepoint.com/sites/CRM. Since we have the full URL to the SharePoint site already, I wrote a bit of Liquid to extract the server URL from it – see below.

Putting It All Together

Now that we have all of the parameters we need, we can fill in the blanks of the following code:

{% assign sharepointdomain = "" %}
{% for c in sharepointsiteurl %}
    {% assign char = c | string %}
    {% assign sharepointdomain = sharepointdomain | append: char %}
    {% if sharepointdomain endswith 'sharepoint.com' %}
        {% break %}
    {% endif %}   
{% endfor %}

$(document).ready(function() {  
    DynPCA.UserId = '{{user.emailaddress1}}';
    DynPCA.Auth.Params = {
        ClientId: 'your Application ID',
        Tenant: 'your Azure AD Tenant ID',
        RedirectUri: window.location.protocol + "//" + window.location.host,
        ApiScopes: '{{sharepointdomain}}',
    };
    DynPCA.Auth.Init();  
    DynPCA.App.ExecuteRequest(
        'GET', 
        null, 
        'json', 
        true, 
        "{{sharepointsiteurl}}/_api/web/getfolderbyserverrelativeurl('{{url}}')/files", 
        { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" })
    .done(function (data) {
        var table = $('<table class="table table-striped">').insertAfter('.entity-form');
        table.append("<tr><th>Document</th><th></th></tr>");

        $.each(data.value, function(i, e) {
            table.append("<tr><td>" + e.Name + "</td><td><a target='_blank' href='https://ecjul18.sharepoint.com" + e.ServerRelativeUrl + "'>View</a></td></tr>");
        });
    }).fail(function (jqXHR, textStatus, errorThrown) {
        alert(errorThrown);
    });
});

The first bit of code gets the SharePoint server URL from the full SharePoint Site URL. Next, I’m leveraging the DynPCA class that Colin Vermander created as part of his Dynamics Portals Companion App project. This code takes care of acquiring the SharePoint OAuth token, and adding it to subsequent requests when you call the DynPCA.App.ExecuteRequest function. The code is mostly as what’s available on GitHub, except with the changes described in my previous blog post to get a proper SharePoint token. I setup the necessary parameters for the DynPCA class, including the username of the current user (which should be their email address in Dynamics 365), the Client ID and Application ID discussed above, and all of the other parameters we’ve got from our Liquid code in the Part 2 of the series. Finally, I make the call to the SharePoint REST API to get the files in the folder we determined previously, and then I append a simple table based on the results of that request, which includes the file name, and a link to the file.

And with that, you now have a table listing the documents located in the SharePoint folder associated with the current Case record! Of course, the UI is a bit rudimentary, but it is functional. To see the full source code for my Web Template, including the DynPCA dependencies and some simple logic to check if there are no folders for the current entity, click here.

You could also take this a step further and display files that are located in child folders since this code does not take child folders into account.

In the next/final post in this series, I’ll get into how we can upload files to the folder, and why this introduces a bit more complexity.

3 responses to “Adding SharePoint Integration to the Employee Self-Service Portal Without Server-side Code – Part 3”

  1. […] Use the SharePoint REST API to display a list of documents in the SharePoint folder related to the c… […]

  2. Colin says:

    Will the bearer token end up in your JS code somewhere? I haven’t tried running it but I assume it would and accessible to the client browser as DynPCA.Auth.Client.GetToken() code stores that token in the browser storage…if so that bearer token could be re-used in other REST API requests and because that application grants full site collection read then other items within that site collection could be accessed, the whole SharePoint site could potentially be accessible

  3. Nicholas Hayduk says:

    Yes, it would be available in the browser storage, and it could be reused.

    In the scenario we used this in, the users have access to the entire SharePoint site collection, so this wasn’t an issue. But it’s great that you pointed it out – something that others should keep in mind.

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.