Retrieve contents of File Data Type field in Dynamics 365/ CDS using JavaScript/ client code.

Follow my blog for more interesting topics on Dynamics 365, Portals and Power Platform. For training and consulting, write to us at info@xrmforyou.com

Few months back I wrote an article on File Data type in Dynamics 365/ CDS where I explained the details of this data type and explained how you download the content of the field using C# code.

After that I received loads of request on how I can do the same using JavaScript. And here is this blog where I show in detail on how you can do that.

For this demo, I have created a file data type field on contact entity – File Content (cr947_filecontent)

image

Then I go ahead an upload a file on one contact record.

image

Ok now the tough part. How to download this file content from your client script if required? Well, let’s see how you can do this.

First things first. Below is the URL Format to download the file content for a file field for a contact record.

https://<crmurl>/api/data/v9.1/contacts(<contact_id>)/cr947_filecontent?size=full – This will download the content in base64 format string.

https://<crmurl>/api/data/v9.1/contacts(<contact_id>)/cr947_filecontent/$value?size=full – This will download the content as byte array.

If your file size is less than 16 MB, then depending on how you want to download the file, you can use the appropriate URL.

However if your filesize is more than 16MB, it wont’ work. This is because you if you use the same URL to download the content for a filesize more than 16MB, you will get an error – “Maximum file size supported for download is [16] MB. File of [17 MB] size may only be downloaded using staged chunk download.”

So let’s see how we can have a common function to handle all these scenarios. Below is the code for the same. I have decided to go ahead with the base64 content.

Also if you observe here, I am downloading the file content in chunk of 4MB. Also observe I am using the “Range” header to set the bytes count that I want to download.

function makeRequest(method, url, startBytes, increment) {
    return new Promise(function (resolve, reject) {
       var request = new XMLHttpRequest();
       request.open(method, url);
       request.setRequestHeader("Range", "bytes=" + startBytes + "-" + (startBytes + increment - 1));
       request.onload = resolve;
       request.onerror = reject;
       request.send();
    });
}

async function PrepareFile() {
    var startBytes = 0;
    var increment = 4194304;
    var url = "https://<crmurl>/api/data/v9.1/contacts(8da6e5b9-88df-e311-b8e5-6c3be5a8b200)/<field_name>?size=full";
    var finalContent = "";
    var fileSize = 0;
    var fileName = '';

   while (startBytes <= fileSize) {
       debugger;
       var result = await makeRequest("GET", url, startBytes, increment);
       var req = result.target;

      if (req.status === 206) {
          finalContent += JSON.parse(req.responseText).value;
          startBytes += increment;

         if (fileSize === 0) {
             fileSize = req.getResponseHeader("x-ms-file-size");
             fileName = req.getResponseHeader("x-ms-file-name");
          }
       }
    }
}

PrepareFile();

I am calling PrepareFile() method which is doing the loop through. “finalcontent” is the variable which will have the entire base64 content.

How to use the base64 content and download it through browser? I am leaving that for a homework.

Hope this helps!

Debajit Dutta

(Microsoft MVP)

Custom integration between Dynamics 365/CDS and SharePoint using C# and SharePoint REST API ? Learn how to create a SharePoint Add-in and generate authentication token–Part 3

Follow my blog for more interesting topics on Dynamics 365, Portals and Power Platform. For training and consulting, write to us at info@xrmforyou.com

If you are directly on this blog post, I suggest you start from the first blog post of this series to get the context.

So I am on the final blog of this series. And here I am going to generate the authentication token to finally connect to SharePoint. Here we will deal with two most important properties of the Add-in, Add-In ID and Add-In Secret. Using these two properties now we will construct the access token.

Let us achieve this in the following steps

  • Open your VS and create a Console Application. ( I am using VS 2017 and created a console application with .Net framework 4.6.2)

  • After your project is created we need to add the SharePoint Dependencies. To do this right click on References and Manage NuGet packages and look for a package named AppForSharePointOnlineWebToolkit and install the package.

While trying to add the reference you may face an issue saying Microsoft.IdentityModel.dll was not found so package could not be installed.

If that’s the case, add Microsoft.IdentityModel.dll using NuGet package.

  • Post doing step 3 as well you will not be able to reference SharePoint Dependencies since it again looks for another dll named Microsoft.IdentityModel.Extensions dll.
  • Include the reference for Microsoft.IdentityModel.Extensions.dll

  • Now let us try to install the package named AppForSharePointOnlineWebToolkit. Not only this package will add the SharePoint Dependencies but also includes the class files TokenHelper.cs and SharePointContext.cs
  • Now we have included all the dependencies required for the operation. Make sure to include the below configuration in App.config file
  • Use the Client ID and Client Secret of the Add-In and replace its values in App.Config file. This is because TokenHelper.cs class will grab the id and secret from the application’s configuration file. Add the following piece of code in your application to generate the token.
string siteUrl = "https://xrm20208.sharepoint.com";

//Get the realm for the URL

string realm = TokenHelper.GetRealmFromTargetUrl(new Uri(siteUrl));

//Get the access token for the URL.  

string accessToken = TokenHelper.GetAppOnlyAccessToken(TokenHelper.SharePointPrincipal, new Uri(siteUrl).Authority, realm).AccessToken;

  • As you can see in the below screenshot my token is generated successfully.

Yahoo! Now that is some relief right? The token is now generated and you can passing it as a bearer token while making any calls to SharePoint REST API. I am not going to show you how you are now going to consume the REST API. We have innumerable good SharePoint blogs for the same. So I leave the remaining part for you to explore.

Hope this helps!

Debajit Dutta

(Microsoft MVP)

Custom button to save a record and stay on the same step without moving to the next or previous step inside a Webform step in PowerApps portals/ Dynamics 365 Portals? Check this out!

Follow my blog for more interesting topics on Dynamics 365, Portals and Power Platform. For training and consulting, write to us at info@xrmforyou.com

Few months back I posted an article on how you can develop a custom button for Save as draft functionality on an Entity form in PowerApps portals. On that post I have received multiple queries on how we can do the same inside a webform. It’s quite easy and my blog is dedicated to that.

But before I go ahead and write how I can do the same in WebForms, let’s see under what circumstances you would need that solution.

Inside a WebForm in Dynamics 365 Portals or PowerApps portals, we always have the following behavior.

The first step in the WebForm has the “Next” button. Obviously you can rename the Next button, but the behavior is always when you click that button it goes to the next step.

image

In all intermediate steps, you have the next and previous button

image

In the final step, you have the Submit button.

image

Now the issue here is whatever button you click, you are either taken to the next step or previous step. There is no button which when clicked will save the record but will not redirect you to the next page kind of “Save” button which just save the record and does not navigate.

Now that we understand the requirement, the next step is to implement the same.

The first thing is to insert the “Save” button. And let’s say we will always put it after the first button.

So to make the code generic, we write the following code.

$(window).on("load", function () {
    $fb = $("div.actions input[type='button']:first");
    $("<input type='button' id='btnSave' name='btnSave' value='Save' class='submit-btn btn btn-primary form-action-container-left' />")
       .insertAfter($fb);   $("#btnSave").bind("click", function () {

       // if you want you can perform some custom logic before you call save.
       WebForm_DoPostBackWithOptions
          (new WebForm_PostBackOptions(undefined, '', true, '', '', false, true));
    });
});

If you observe the code carefully, we are taking the first button from the action buttons and inserting our custom save button right after that. Also the trick is to call the WebForm_PostBackOptions with the name of the previous button.

And then finally use the code in the Custom javascript section of each webform step.

image

And now once you refresh the portal cache and browse the webform, you can see the Save button.

image

And now let’s see all this in action. Just observe the below video where I click on Next and it saves the record but does not move to the next step. Kind of stuff we expected right?

Hope this helps!

Debajit Dutta

(Microsoft MVP)

Custom integration between Dynamics 365/CDS and SharePoint using C# and SharePoint REST API ? Learn how to create a SharePoint Add-in and generate authentication token–Part 2

Follow my blog for more interesting topics on Dynamics 365, Portals and Power Platform. For training and consulting, write to us at info@xrmforyou.com

If you are directly on this blog, I suggest you go through the first blog of this series.

In our previous blog, we created the SharePoint Add-in. In this blog we shall be providing this APP permissions on sitecollection.

To apply permissions to the generated Add-In either you can visit SharePoint Tenant Administration Site or via AppInv.aspx page

Visit SharePoint Admin center to do this. Go to <admin_site_url>/_layouts/15/appinv.aspx

image

Use the App Id that you created as per directions in previous blog and click on Lookup button to retrieve the APP Details.

image

The important thing is the App’s permission.

If you want to provide full control at the tenant level use the following permission XML

<AppPermissionRequests AllowAppOnlyPolicy="true">

<AppPermissionRequest Scope="http://sharepoint/content/tenant" Right="FullControl" />

</AppPermissionRequests>

image

Once you click Create you will be presented with permission dialog. Click Trust It to grant permissions

clip_image002

Now your Add-In is ready for use. As we granted tenant-level permissions you might be wondering if I need do the same for specific site collection. No worries this can he handled as well. Create Add-In app in your Site Collection using Blog Post 1 and follow the similar approach but modify the permissions XML as below:

<AppPermissionRequests AllowAppOnlyPolicy="true">

<AppPermissionRequest Scope="http://sharepoint/content/sitecollection" Right="FullControl"/>

<AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web" Right="FullControl"/>

</AppPermissionRequests>

In this way we create Add-Ins and grant permissions to Add-In. In Part-3 of my blog I will show you how to generate token from Add-in.

Hope this helps!

Debajit Dutta

(Microsoft MVP)

Custom integration between Dynamics 365/CDS and SharePoint using C# and SharePoint REST API ? Learn how to create a SharePoint Add-in and generate authentication token–Part 1

Follow my blog for more interesting topics on Dynamics 365, Portals and Power Platform. For training and consulting, write to us at info@xrmforyou.com

Before I go ahead, while this blog depicts on how you can generate the Authentication token to integrate between Dynamics 365 and SharePoint, this can be applied to any application trying to authenticate with SharePoint online to consume SP REST API’s. The methodology presented here can be applied for all applications.

Your day as a consultant can throw a lot of surprises and this was one of them. We had a custom integration between Dynamics 365 online and SharePoint. online And the connection was being completed using username and password authentication by consuming Sharepoint REST API services.

And one fine day this stopped working. There were some access policy changes on Azure and now the code was not able to generate a request digest using username-password credentials. It was always coming as null and authentication was failing. Moreover client was also not okay to use a service or end-user account for authentication.

If you are on the same boat, don’t be worried. This blog is explicitly on how you can handle this scenario. And that is using SharePoint add-in.

There are multiple ways to register SharePoint add-in such as using Visual Studio, the Seller Dashboard, or an AppRegNew.aspx page. In this blog post we will register add-in using AppRegNew.aspx in tenant which is one of the recommended approaches.

To do this we need global administrator privileges which is SharePoint Administrator role in SharePoint site. Let us now try to register your add-in in the following steps:

Step 1: Go to <site-colleciton-url>/_layouts/15/AppRegNew.aspx using browser.

clip_image002

Step 2: Fill up the details to create add-in

 

· Client Id – Add in ID basically a Guid that can be generated (Generated button is used to generate Guid) or paste Guid into AppRegNew.aspx

· Client Secret – Add in Secret basically a string that can be generated using Generated button. Usually the secret expires in one year.

· Title – Name of the add in

· App Domain – The host name of the remote component of the SharePoint Add-in. he add-in domain must match the URL bindings you use for your web application. Do not include protocol (“https:”) or “/” characters in this value. If your web application host is using a DNS CNAME alias, use the alias. Examples: www.localhost.com, www.contoso.com:3333 and www.scholarship.com

· Redirect Uri –The endpoint in remote application. The value must be a complete endpoint URL including the protocol, which must be HTTPS. For example: https://www.localhost.com, https://www.contoso.com/Default.aspx

Step 3: Provide all the details and click Create.

clip_image004
clip_image005

Now that we have created the add-in, it’s now time for providing the app the required permissions to your sitecollection. In the next blog will shall be doing the same. Make a copy of your application details that you just created. We shall need it in the next blog.

Hope this helps!

Debajit Dutta

(Microsoft MVP)

Query Entity Permissions for a portal user using Liquid in PowerApps portals/ Dynamics 365 Portals

Follow my blog for more interesting topics on Dynamics 365, Portals and Power Platform. For training and consulting, write to us at info@xrmforyou.com

Entity permissions are a great way to control record access in your Dynamics 365 Portals. You can have fine grained control at individual record level. But ever wondered if you can determine the portal user privileges on a particular record that the portal user is viewing? Cometh the hour, cometh the champion, our very own liquid in Dynamics 365 Portals.

Using liquid you can determine the permission a portal user is having on a record they are viewing. Let’s see how we can accomplish the same.

For this demo, I have created a sample Web Template. Before I go ahead and show you the template code, below are the configurations that I made.

1. Created a portal user

2. Assigned a web role to the portal user

3. Provided Entity permission to the web role for contact entity. Screenshot below. Please note I haven’t provided “Append To” permission.

image

Below is the code for my web template

As you can see, the entity liquid tag has permissions object. And the permissions object have properties like can_create, can_read etc. to check for user privileges on the record.

When I run the page for a specific contact, below is output.

image

As you can see “Can Append To” is false because I haven’t provided append to permissions in the Entity permission.

Hope this helps!

Debajit Dutta

(Microsoft MVP)

Understanding “Restrict Read” Web Page Access control rule in Dynamics 365 Portals/ PowerApps portals

Follow my blog for more interesting topics on Dynamics 365, Portals and Power Platform. For training and consulting, write to us at info@xrmforyou.com

Restrict Read” – A privilege which is perhaps most misunderstood. And every session I go when I start explaining the concept of Restrict Read, participants are like – Come on! This is not what Restrict read means.

What is ARFID? - Columbus Park

To give a quick background we have Web Page Access Control rules and under Web Page access control rules we have Grant Access and Restrict Read. The problem arises with Restrict read.

So let’s create a restrict rule for one of our webpages. The web page name is “Restricted Page”.

image

Now what happens? The moment I created this Restrict Rule, the Restricted Page along with all the web files under this page (defined by scope), are restricted for all  users in all web roles. In other words, the moment you create a restrict rule for a page, the page is blocked from all portal users. And then you have to assign webroles explicitly to this rule to enable this page only for users in the specific role.

So I go ahead and assign “Employee Web Role” to this rule.

image

The moment I do this, all users in Employee Web Role shall be able to see the Restricted page. So the gist is –

“When you create a restrict rule for a page, the page is blocked for all. And then you have to assign webroles to this rule to explicitly make this page available to users in that webrole.”

Hope things are clearer if ever you had a doubt about Restrict read.

Hope this helps!

Debajit Dutta

(Microsoft MVP)

{Solved} Web Page cannot be set to self–Error while browsing PowerApps/ Dynamics 365 Portals

Follow my blog for more interesting topics on Dynamics 365, Portals and Power Platform. For training and consulting, write to us at info@xrmforyou.com

Recently we had an issue with one of our Customer portals. Everything was working fine in DEV and UAT environments. However after portal deployment in production environment, customers reported they are unable to browse the portal. Whenever they are trying to access the portal, they are getting generic portal error which displays a error code and asks to contact system administrator.

For a quick resolution, we disabled custom errors in the portal. Then when we tried to browse the portal we got the error – “Web Page cannot be set to self”.

I was kind of taken aback because I have never received this error before.

WHAT JUST HAPPENED! - Lolcats - lol | cat memes | funny cats ...

Regathering myself, I just realized then when the portal is launched, it’s the home page of the portal which is displayed. So there must be an issue with the home page.

And then I went ahead and opened the home page of the portal. And I could see as below

image

Not sure how this happened and investigation going on. But my I guess it happened during portal migration. Nonetheless, I removed the parent page, cleared portal cache and then browsed the portal.

And now to our delight, our beloved portal is back.

Hope this helps!

Debajit Dutta

(Microsoft MVP)

How to get device location in Dynamics 365 for Mobile

Follow my blog for interesting topics on Dynamics 365, Portals and Power Platform.

The world is into mobile devices and Dynamics 365 is not left far behind. With unified interface, user’s are now getting seamless experience across all devices starting from web browser in desktop clients, to phones and tablets.

Dynamics 365 is well and try mobile now.

Dynamics 365 for phones, Power Apps, and Resco: What are the ...

And when you are in mobile platform, you may feel the need to know device location. And believe me, Microsoft have provided you an API which can give you just that. Following is the code to do that.

Xrm.Device.getCurrentPosition().then(
    function success(location) {
       console.log("Latitude", ":", location.coords.latitude);
       console.log("Longitude:", location.coords.longitude);
    },
    function (error) {
       console.log("error in determining location :", error.message);
    }
);

Please note that the above code will only run on mobile platforms (tablets & Phones). Trying to run it on Web browser in desktop will give you an error – “Operation is not supported by platform.”

Hope this helps!

Debajit Dutta

(Microsoft MVP)

Where does Dynamics 365 Portals/ PowerApps portals store theme information when you change portal theme using PowerApps portal editor?

For training and consulting, write to us at info@xrmforyou.com

Recently I published a blog on the new preview feature for PowerApps portals where it allows you to change the portal theme from PowerApps portal editor. Check this here.

While I received quite a few queries on the same, one of the interesting questions I got is – “Where does Portals store the current theme that is selected? Can I change it without PowerApps portal editor?”

That left me puzzled a bit. Honestly I never thought on those lines.

question mark.jpg

Initially my hunch was Portals must be storing this internally. But somehow I kept the belief that like many other settings, this must also be a site setting which is maintained by the portal.

And finally it was there! The site setting name is “ThemeFeature”

image

To test it, I went ahead and changed the portal theme using PowerApps portal editor, the record is updated with the new “selectedThemeId”.

To me not a very useful information honestly but certainly better to know than not knowing it.

Hope this one helps!

Debajit Dutta

(Microsoft MVP)