Category Archives: Uncategorized

Making a better User Experience with PowerApps Component Framework from sketch – Part 4 – The Final Showdown

Published / by AK / Leave a Comment

You can read previous post Part 1, Part 2 and Part 3.

Seeing is believing

It took me 2.5 days to learn and figure out the design and new technologies I need to build the component.

Less than half a day, the mock version of the component was completed. The component was loaded on the form, the dialog was shown with the mock file list, the Flow was triggered to attach a hard-coded SharePoint file to an email as an attachment.

Now, I can prove the team that the PCF control works. I can show it to users how the component can change their life drastically.

When users saw the new UX, it just blew away them. They just forgot the inconvenience with the out-of-the-box user experience. We shot down Top 1 issue from their bounty list.

Keep yourself connected

Though the mock version was smooth, there were a few issues (as expected) I faced. When I tried to use WebAPI in PCF, it always return null. I checked my old PCF which used to be work. It was not working anymore. I looked at other PCF examples from the community. All looked same as mine. Mine was not working. I had no clue.

So, I reached out Natraj (God Mode of PCF). He kindly showed me the direction. It turned out PCF team had introduced <feature-usage> tag in manifest. I had to include WebAPI feature in manifest file to use WebAPI. It was a life saver.

A blocker? Reach out to the community.

You don’t have to be alone solving the issue.

Coming to the end

Just over 1 day of building and trouble shooting, I had a fully working version of the component. In fact, the total build time was less than the initial design and exploration.

If you ask me “Would you spend more time thinking and playing than actual building?”, my answer is “Always”.

I encourage my colleagues to spend more time exploring than completing tasks. Completing the task is the last thing I worry. To me, understanding fundamentals and visualising the process are more important than just completing the task. Once you fully understand it, the rest is a piece of cake. You don’t need to look back. You can keep moving forward.

Limitations or future enhancements

There are many limitations and a few things I couldn’t include in this first version.

  1. Support sub-folder in SharePoint – The component does NOT currently support the navigation of sub-folder in SharePoint. I had the working FetchXml query and will add it in next version.
  2. Support attaching documents from Notes – I want to allow users attaching from Notes of an associated record, similar to SharePoint documents.
  3. Support local file attachment – This will make the component one-stop shop for attachments. You can attach files from SharePoint, Notes and local files.
  4. A managed solution package (with potential AppSource)

Configuration

After I posted the component in LinkedIn, a few people reached out to me how to configure the component and its Flow. I had privately responded to them.

The component accepts 3 properties

  1. Regarding Id – Can be bound to any text field. However, I recommend creating a separate text field as I need to update it’s value to trigger onChange event in Dynamics to refresh the grid. Currently, it is the only supported way to refresh the grid.
  2. SharePoint Site URLs – You can include multiple site collection addresses with comma separated value. For instances, https://mysite.sharepoint.com/site1, https://mysite.sharepoint.com/site2
  3. API/Flow URL – The URL of Flow end point. It will look like this “https://prod-19.australiasoutheast.logic.azure.com:443/workflows/…invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=…&spsite={0}&spfilepath={1} . Get my Flow here. Once you imported the Flow, copy the HTTP URL from the trigger. Then, append the URL with &spsite={0}&spfilepath={1} and set it as property value.

Last step is to hook up JavaScript to refresh the grid. Create a JavaScript web resource or update the existing one with the following script.

function refreshAttachmentGrid(executionContext) { 
var formContext = executionContext.getFormContext();
var attachmentGrid = formContext.getControl("attachmentsGrid");
attachmentGrid.refresh();
}

Then, add the web source to the Email form and add onChange event on the attribute you bound with PCF to call refreshAttachmentGrid function.

That’s all you need to configure to use the component.

I hope you enjoy this mini-series of blog. You can read Part 1, Part 2 and Part 3.

I will be back with another cool PCF that works in both model-driven apps and canvas apps. Stay tuned. Bye for now.

Making a better User Experience with PowerApps Component Framework from sketch – Part 3 – The Slow Start

Published / by AK / 1 Comment on Making a better User Experience with PowerApps Component Framework from sketch – Part 3 – The Slow Start

You can read previous episode Part 1 – The Problem and Part 2 – The Sketch.

The Slow Start

I always take time to figure out the suitable frameworks and libraries, try them out and learn them, as the first stage, before building. That makes me a slow start. Sometimes, notoriously slow. It is, to me, worthy as it will give me an extra boost from the mid stage.

List to free you up

Firstly, I listed down main questions/challenges in this problem

  1. Office UI Fabric – How would I use? Where would I learn? How would I test?
  2. Popup dialog – Which dialog should I use; PCF Popup service or Modal from Fabric?
  3. Getting document lists from SharePoint – How would I retrieve document lists from SharePoint?
  4. Getting a file content from SharePoint – How would I read the file content from SharePoint? Using JavaScript or custom WebAPI or Microsoft Flow?

Intelligence == Liability

This is something I learned during my early day with Test Driven Development (TDD). Smart people do not write unit tests on their code, because their code always work. By the time, they write unit tests on their code, it is eventually too late.

The same concept

Writing down a list of things you need to do can be challenging. It can be seen as waste of time, lack of creativity and extra works.

To me, it is the total opposite. With list, you don’t need to memorize what you need to do, thus it frees up your brain. As a result, you can shift your focus to new stuffs for boosting the creativity.

UI Fabric

It is a preferable choice in creating user interface that mimic Microsoft Office products. Besides, it is built with React. No brainer here. But the problem is I had never used UI Fabric before.

I went to UI Fabric and started playing with controls and styles.

The best thing about UI Fabric documentation is you can export the sample code to CodePen and play around with it. It was an ultimate time saver, as I didn’t need to setup UI Fabric in my machine.

I learnt how to use several components like

  • Detail List for showing files from SharePoint
  • Icons for displaying appropriate file icons so it is visually appealing
  • Scrollable Pane for making the popup dialog compact even with a long list of files
  • Search for allowing users to search files so they don’t need to scroll through
  • Button for triggering a logic to attach files from SharePoint to Email attachments in CDS
  • Progress Bar for informing users attaching files is in progress so they know it is doing something

Popup dialog

First, I looked at Popup service in PCF. I felt its implementation is not very friendly plus minimal documentation. It would be perfect for a simple dialog.

I turned into Modal component in UI Fabric. Since I will be using other UI Fabric components, I decided to stick with Modal from Fabric. Plus, I can test it CodePen whereas I have to setup a PCF project for Popup service.

Getting documents from SharePoint

You cannot retrieve documents from Advanced Find although you can see it in the query.

SharePoint Document in Advanced Find
SharePoint Document in Advanced Find

So, what did I do? I used Developer toolbar and inspected the network traffic. It gave me FetchXML I needed and the response I can work with.

Getting a file content from SharePoint

I tested reading SharePoint file using “fetch” library”, I immediately hit into CORS issue.

Therefore, I had to develop a custom WebAPI. I decided to use Microsoft Flow as a HTTP endpoint, since Microsoft Flow already has the out-of-the-box SharePoint connector.

Slow is smooth. Smooth is fast.

United States Navy SEALs

Up to this point, I spent almost 2 days to figure out and play around with most components I needed to use. I hadn’t written a single line of code in the PCF project.

Now, I asked myself the same question.

Am I ready to build? Definitely, YES.

Yes, I am ready to build the component by myself. Besides, I am ready to give a definitive guide to others for build the component I want.

Next, I will share you how long it took me to build a working component (excluding these 2.5 days:0.5 day of sketching and 2 days of learning). Stay tune for the final episode.

Making a better User Experience with PowerApps Component Framework from sketch – Part 2 – The Sketch

Published / by AK / 2 Comments on Making a better User Experience with PowerApps Component Framework from sketch – Part 2 – The Sketch

Part 1 – The Problem can be found here.

Time for Proof of Concept (PoC)

I like building canvas app, for Proof of Concept (PoC) purpose. It is so easy. Drag and drop, a few clicks and formula, and then you can see the result.

I thought of building a canvas app in the first place. However, I quickly discarded the idea as soon as I figured out there was no easy way and it’s going to take much time.

So, I turned into PowerApps Component Framework (PCF).

Sketching the idea

I love using pencils and paper. It is so physical and gives me the first hand experience. After doodling a couple of pages, I came up with the following sketch.

On the paper

I am trying to build a button using PCF that can be placed on the email form.

When users click it, I want to show a list of SharePoint documents from the related record (regarding) as a dialog. I want users to select multiple files and attach them to the email with a single click.

When users click Attach button in the dialog, it will call a WebAPI that will return the file content from SharePoint. Then, the component will create an attachment in CDS email, and hide the dialog.

From Requirements to Build

Sketching the idea is easy. Listing down requirements is straightforward. Saying “I want these” is a piece of cake.

But, the build is a real challenge. It is even more challenging if a builder doesn’t know technologies, frameworks, libraries and their abilities to make his life easier. This is where a leader can make difference.

Guess to solve

For instance, Person A asks you to create a web page, saying “I want a responsive web page on every device. You can probably use CSS and tweak positions, width, and alignment to make them responsive.”

There is a clear requirement which is a responsive design. But the solution to the problem is blur. No definitive. It is more misleading when Person A starts talking about tweaking position, layout and alignment. A builder can easily drift away with tweaking x and y, width and height, and alignment in basic CSS, which works on every single browser and device.

Make a difference

Now, what about this. Person B says “I want a responsive web page on every device. You can check out Bootstrap, especially its layout/grid system. Let me know if you have a challenge. We will figure it out.”

Whom would you love to work with? Person A or Person B?

To me, it is definitely Person B. A leader who gives you a clear direction but makes you learn it yourself. At the same time, he doesn’t mind getting his hand dirty.

Now, back to the sketch I drew. It’s time to ask the important question myself, and I must answer it honestly.

Am I ready to build?

The answer is NO. There are a couple of things I needed to figured out.

In the next post, I will write how to figure out what I needs to learn and try out before building an actual component. Stay tuned for Part 3 – The Slow Start.

Making a better User Experience with PowerApps Component Framework from sketch – Part 1 – The Problem

Published / by AK / 4 Comments on Making a better User Experience with PowerApps Component Framework from sketch – Part 1 – The Problem

Since the public preview of PowerApps Component Framework (PCF), I always want to build a component that enhances the user experience (UX) in model-driven apps in Common Data Service (CDS) or Dynamics 365.

Recently, I had an opportunity to build a component with PowerApps Component Framework (PCF) that will save several mouse clicks from each user.

I literally started building a PCF component using a paper and a pencil. I thought of sharing my experience in this mini-blog series.

Activity and document management in CDS

People uses Customer Relationship Management (CRM) system to keep track of every interaction with customers in one place. If users have to juggle between many applications to see all interactions, it will not be productive.

CDS includes an activity management, tracking emails, tasks, phone calls, letters, and appointments. Users can sync these activities between CDS and Exchange.

Being able to send an email directly from CDS is convenient to users, as they don’t need to switch to Outlook to send an email. If an email is sent from a case, the email will automatically associate with the case, giving a 360 degree view.

Today, users often use SharePoint as a central document management system to store documents related to cases and customers. CDS offers out-of-the-box integration with SharePoint, thus integration is merely a couple of mouse clicks. Everything is perfect.

Attaching documents in Email

When users send an email to the customer in CDS, they often need to attach documents from SharePoint by going through following steps:

  1. Open a case record
  2. Navigate to Documents tab
  3. Click a file to download*
  4. Choose a local folder to save the files* (several clicks to navigate and create a new folder)
  5. Navigate to Activity tab
  6. Add a new Email
  7. Save the email
  8. Click Attach File button from the command bar*
  9. Choose a file from the local folder* (several click to navigate to the correct folder)
  10. Repeat the whole process if the user needs another file from SharePoint

*Repeat if more than one file is needed


A problem?

You can clearly see the user experience (UX) is horrible. Look at followings:

  1. Users have to download each file individually
  2. Users have to store files locally in an organised manner
  3. Users will not know know if local files are outdated
  4. Users have to attach a file individually
  5. The worst part? Users have to go through the whole process if they forget to download a file.

What if users can attach documents from SharePoint to an email directly?

It will be a time saver to users. Imagine users can attach multiple files from SharePoint to an email in CDS.

In the next post, I will show you how I plan to tackle the problem. Stay tuned for Part 2 – The Sketch.

Six months after deploying my first PowerApps

Published / by AK / Leave a Comment

This post is more of rant than evangelist.

In October 2018, I had involuntarily involved in developing PowerApps for one of our clients at work. “Why involuntarily?” you may ask. Well, although I mainly work with Microsoft platform, I play around with iOS and Android native app developments and help out my friends. So, I fairly know the biggest challenge with mobile app development, making your app to work across different devices.

PowerApps is great. I have no doubt about it. All canvas-apps run inside PowerApps native app on your mobile, thus making it very different from cross-platform development in mobile app. It also means you have no control over the release of PowerApps native app.

Regardless of my strong objection, we managed to deliver the app in 10 days. The purpose of the app is to transform their paperwork of auditing farms. Basically, admin will create audit records in D365 and assign to auditors, then auditors will download records to their apps for offline use, drive out to remote areas for auditing (which also captures photo and signature). When auditors arrive back to their home at night, they sync their offline data to D365 and get newly assigned audits. Photos need to upload to their Google Drive. Why not? Microsoft Flow has out-of-the-box connector to Google Drive. Easy peasy.

Then, the client wanted to add a new functionality which will share photos uploaded in Google Drive to the audited farm. Although you can share files/folders in Google Drive, out-of-the-box connector is not capable of doing it. After going through Google Drive REST APIs, we solved it by creating a custom connector. To deliver all these functions in 10 days was impressive. It was working fine. Well … for two months.

In December, the client told us some of their auditors were facing issues with syncing records. We enhanced our app for a better performance. During the enhancement, it was all fine. When the app was re-opened again, it showed over 200 errors on one of global variables in the app. Suddenly! Set and Patch function on record type global variable didn’t work anymore. (You can find the similar issue here, though I didn’t report it).

I ended up with re-creating an app almost from scratch again. Tweak and fix. Again and again. One of the challenges with web player is you can’t test offline mode. SaveData and LoadData doesn’t work. I hope Microsoft will at least create stubs for these two functions for web player in the future. Having to test it on the device, you have to publish the app, and open the app at least twice in the device to see the latest version. It is not productive at all, but we managed to fix all issues.

But, there was another problem. Microsoft has released the new version of PowerApps and unfortunately it was a bad version. Without noticing the bad version, I kept working on the app. After publishing to test it on my device, it was too late. There was no way to return. If I rolled back to the working version, all my changes will be lost. If I stick to the current version, it can’t be tested. It didn’t look good at all.

Luckily, Microsoft released the bug fix over the weekend and the original issue was gone. But, again, the app was starting to behave weird. Functionalities used to work were not working anymore. For example, if I rolled back to the old working version, it worked. But, not on the latest PowerApps version. It is so frustrating for a developer. You have no control over which PowerApps runtime you want to choose. Microsoft dictates it. Because of it, one bad runtime version can create many issues even if you don’t make any changes.

During the enhancement, we started to notice errors in listing Google Drive files in Microsoft Flow. After searching Google Drive REST APIs, it turns out Google limits items returned from API to 100 by default and it can be changed. However, there is no way to define the paging size in out-of-the-box connector. We didn’t have the issue in UAT and early days of production go-live since items were less than 100. But, now we have an issue. As usual, a custom connector saved our life.

All issues seem to be sorted out, at least, for now. Hopefully, the app will behave nicely for next two months. But, I learned following lessons.

  • PowerApps is easy but not necessarily simple – a lot of gotcha and similar functions with totally different behaviours.
  • A lack of ability to control PowerApps version – one bad version will break your app into pieces just by publishing without making any changes. If it happens in development phase, it will stale the timeline.
  • Out-of-the-box connectors are useful for demo but not reliable for production – always reference to the source API documentation, not Microsoft Flow documentation.
  • Community is great but not all issues are resolved – looking at the example with Set and Patch functions in above link, it took about 2 months to recognise the issue by Microsoft PowerApps team. The worst part is it is not resolved yet.

Channel Integration Framework with Twilio – Part 1

Published / by AK / 2 Comments on Channel Integration Framework with Twilio – Part 1

I have posted the video of incoming call using CIF here. It is a live working demo using Twilio trial account. I am going to share my experience of making this so anyone can easily setup the basic features and start exploring more awesomeness.

I have tested the public preview of Microsoft Dynamics 365 Channel Integration Framework. It was before Christmas and New Years holidays. Moving house over the holiday period kept me occupied for weeks.

Last week, I started to look into CIF again. During the public preview, I had issues with incoming and outgoing calls. I was able to connect to Twilio service. Outgoing/incoming calls that return pre-defined messages were successful. However, I couldn’t manage to figure it out to make a call to a real number.

In this post, I am going to cover D365 users responding to incoming calls directly from web interface – without leaving D365 at all.

Preparation

Before we start, please go through followings

Now, we can begin!

Setting up

You will find steps provided in Microsoft documentations are easy to follow. But I find problems with the section to create Twilio functions (https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/channel-integration-framework/sample-softphone-integration#create-function-to-use-with-the-app-service).

According to Readme included in the sample code, you have to create functions in Twilio. I followed the instructions and couldn’t manage to make it work. So, I started with creating a basic client and later add a couple of controllers to the sample code to setup a twilio client.

You can follow tutorials from https://www.twilio.com/docs/voice/client/tutorials/how-to-set-up-a-server-for-twilio-client to create a basic client including TokenController and VoiceController. Creating own controllers give us the whole capability of Web, flexibility and fine grain control of call processes, such as limiting the functionality, dynamic routing which could be stored somewhere else.

In Twilio console, it is very easy to get confused and lost in navigation. However, we can get the information we need from
– Twilio account dashboard at https://www.twilio.com/console
– TwiML apps at https://www.twilio.com/console/voice/twiml/apps
– Phone numbers at https://www.twilio.com/console/phone-numbers/incoming

In short, you need to

Once you have deployed the sample code, you need to configure your trial Twilio Phone Number. First, let’s create a TwiML to route and store it in TwiML Bin. You can find TwiML bin under Runtime or at https://www.twilio.com/console/runtime/twiml-bins/. For testing purpose, let’s create following TwiML.

TwiML
TwiML

You may ask “What the heck ‘ak’ is sitting between Client tag?” Well, it directly relates to the client name of token generated from TokenController.cs

TokenController
TokenController

Once TwiML is saved, go to your phone number and configure its A CALL COMES IN setting by choosing TwiML and choosing the newly created TwiML from Bins.

Phone Number Configuration
Phone Number Configuration

That’s all you need to configure to receive and answer the call using CIF. It takes a while to get it right. Reading Twilio documentations will help you a lot.

Enhancements

You would notice that I use a static TwiML to route to the client in Phone Number configuration. In real world, I think Webhook is a better approach where you can return TwiML dynamically according to implementation of business rules. In addition, TokenController.cs could do similar thing which generates dynamic token for each login user. That way, the call could be routed to the correct client.

Need help?

Reach out to me if you need any help and it is confusing.

Accessing Dynamics 365 WebAPI as an application user without using ADAL

Published / by AK / Leave a Comment

Microsoft has recently posted the documentation for using Postman with Dynamics 365 WebAPI at https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/webapi/use-postman-web-api. This prompts you to login into the application using your credentials to generate a bearer token which is passed to Dynamics 365 WebAPI when a request is made.

However, we, sometimes, need to use an application user to access WebAPI, either for integration testing purpose or for implementing automations. Microsoft has documented server-to-server (S2S) authentication using Azure Active Directory Authentication Libraries (ADAL) at https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/walkthrough-multi-tenant-server-server-authentication.

Although I am a developer, I strongly believe we can (should) write a program only when a process can be manually done. Therefore, tools like Fiddler, SoapUI, Postman are essential tools to me when it comes to testing WebAPIs.

Now, I will show you how we can generate an access token using an application user in Postman, assuming you have already created an application user. If you need detail steps to create an application user, please follow instructions at https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/walkthrough-multi-tenant-server-server-authentication.

In Postman, let’s create a few Postman environment variables.

  • TenantId – to store GUID of Azure Directory ID
  • D365Url – to store the URL of Dynamics 365 instance
  • D365AppId – to store Azure Application Id
  • D365AppSecret – to store Application secret
  • D365Bearer Token – to store generated access token

Environment variables

Environment variables

Then, let’s create a new POST request to https://login.microsoftonline.com/{{TenantId}}/oauth2/token with following data.

Token request

Token request

Now, send a request and it should return an access token (assuming an application user has been correctly setup).

Access Token

Access Token

Now, we need to store the access token to our Postman environment variable called D365BearerToken so that we can re-use it accessing Dynamics 365 WebAPIs. To do this, we need to write a simple script under Tests area.

Writing tests

Writing tests

Pretty easy, right? Now, let’s create another GET request to retrieve the version number of Dynamics 365 instance. The request’s authorization type should be set to ‘Bearer Token’ and its token value should refer to our Postman environment variable D365BearerToken.

Retrieve version

Retrieve version

Now, you can test any WebAPI calls using an application user without relying on ADAL.

What’s next?

Using the same approach, you are not limited to Dynamics 365 ODataQuery in Flow/LogicApps. You can now call any Dynamics 365 Messages using the same approach and perform various tasks.

Creating a custom connector to upload a file to Google Drive from PowerApps – Part 2

Published / by AK / 1 Comment on Creating a custom connector to upload a file to Google Drive from PowerApps – Part 2

Part 1 can be found here.

Swagger time

To create a customer connector, you can upload either a swagger file or a Postman collection. I am not a swagger expert. But, apistudio makes my life easier. Let’s jump onto http://specgen.apistudio.io.

Paste the URL that you used in Postman. Make sure you are using POST. You should receive 202 status after sending the request. One more thing to remember is to click ‘Next Step‘ button instead of clicking tabs. Otherwise, you will need to rework.

Generate swagger

Generate swagger

Enter API Program and contact info. Ensure to use valid Contact Url and Contact Email. What’s next? Next Step button.

Swagger contact info

Swagger contact info

Next is API Info. You can play around with the slider which will change API Base Path and API Path. Give a meaningful OperationId.

API Info

API Info

There is nothing special to do with Headers Info and Params Info, although we will make some manual changes in them. I don’t see (and I don’t know) to make those changes in the generator.

Keep clicking Next Step until you get Open API Spec. There you can download the swagger file.

Open API Spec

Open API Spec

Now, let’s make a few changes to swagger file.

First, we need to replace null with application/json in “produces” collection, and remove the whole section for “content-type”

Remove content-type

Remove content-type

Modify produces

Modify produces

Set default values for api-versionspsv and sig. You can find these values in URL or using Postman.

Set default values

Set default values

Lastly, you need to add parameters for file content, which will be reading from formData as a file type.

Adding file params

Adding file params

That’s pretty much you need to do in Swagger file before creating a custom connector in PowerApps.

Creating a custom connector

Launch PowerApps in the browser and go to Custom connectors, and import your swagger file.

Create a new custom connector

Create a new custom connector

Create custom connector

Create custom connector

Generally, you don’t need to change anything until you get to 3. Definition. At 2. Security, you can still use ‘No authentication’ as the API will authenticate using sig parameter you have provided in the query string. As long as you don’t expose signature parameter, no authorised user can use your API.

At step 3, scroll to Request section where you will see query parameters. Edit api-versionspsv and sig, and change their visibility to internal since we have set default values in swagger file.

Modify visibility

Modify visibility

After changing visibility of api-versionspsv and sig, you can now create a custom connector.

Once it is created, it is time to head into PowerApps. In your PowerApps, while adding a new data source, you can now find your custom connector.

Custom connector in PowerApps

Custom connector in PowerApps

After creating a data source, let’s add some controls to PowerApps and check whether it’s working. I have added PenInput and Button as below. OnSelect of Button, I am going to push the image from PenInput to my Google Drive.

Sample PowerApps

Sample PowerApps

Viola. It is now uploaded to Google Drive.

PenInput to Google Drive

PenInput to Google Drive

PenInput to Google Drive

PowerApps does not work

You know it right? Save, close and open your PowerApps again.

One last thing

This is only an example of how we can easily (of course, I can know say ‘it is easy’) transform any Flow functionalities as custom connectors. This also solves the concern of using Camera control which produces a low resolution photo. With this approach, we can use AddPicture control not only to take full advantage of device camera but also to pick up photos/files which are already existed in the device.

Generally, we don’t need custom connectors if parameter types are simple. In this example, we need Base64. I guess, depending on the parameter type of an endpoint, PowerApps may be passing suitable parameters.

Anyway, we can now invoke all those infinite possible connectors of Flow from PowerApps.

 

Creating a custom connector to upload a file to Google Drive from PowerApps – Part 1

Published / by AK / 1 Comment on Creating a custom connector to upload a file to Google Drive from PowerApps – Part 1

Knowing the limitation

Although Microsoft Flow and PowerApps support ready-to-use connectors for different services, it seems they do not have the same level of offerings between them.

In Flow, for instance, there is a connector for Google Drive and there is a bunch of actions like creating/deleting a file, browsing the folder.

Google Drive Actions in Flow

Google Drive Actions in Flow

However, you cannot use those actions in PowerApps. Apparently, Google Drive connector in PowerApps only works for excel as a datasource.

Google Drive in PowerApps

Google Drive in PowerApps

Additionally, if you pay attention to different image controls, such as PenInput, Camera, Add Media, they have different properties which looks like they are doing the same thing. For example, Camera.Photo returns a Data URI of a picture, while PenInput.Image and AddMediaButton.Media effectively returns a local blob storage URL (appres://blobmanager/<GUID>/<serial number>) which can only be accessed in the app.

Combining with the inability of using full functionality of connectors and meaningless local blob storage URL outside the app, we need look at what else we can do.

Knowing the out-of-box capability

Given that Camera.Photo returns a Data URI string of an image, we can convert it into binary and save it into Google Drive. However, it has another small issue. Camera control in PowerApps does not use the full resolution of device camera. It is ridiculously small (at least to me). If even we can live with small photos, we still need a workaround for other controls.

Out-of-the-box, you can upload images from above control to Azure Blob Storage. Then, from Azure Blob Storage, you can copy the file to the destination you want. This is not a problem for a client who has already had Azure subscription, but not a neat solution for a client who has no prior Azure subscription. Trust me the cost is never a problem (Azure Blob Storage is super cheap) but it’s more about managing different instances. If managing different instances is not an issue, this is a way to go.

Going an extra mile

This is where a real fun starts.

But, we always want to go an extra mile to see what else there. In the bright side, PowerApps allows us to create a custom connector which can be configured in Flow to upload a file to Google Drive.

First, let’s start with creating a flow which will be triggered when HTTP request is received. There is only one trigger available. This is basically a webhook.

HTTP Request Trigger

HTTP Request Trigger

HTTP Request Trigger

HTTP Request Trigger

Then, initialise the ‘FileName’ variable, so we can save the flow. The expression for value is trigger()[‘outputs’][‘queries’][‘filename’] as we are planning to pass query string filename during the request.

Initialise FileName variable

Initialise FileName variable

After saving the flow, expand the HTTP trigger point to grab the URL to invoke

URL to invoke

URL to invoke

Copy that URL to Postman, and append filename query string in URL. Please note sig query string should be kept in secret.

Test from Postman

Test from Postman

After invoking the URL, you will see the Flow is executed. When you open the execute Flow instance, you will see the filename query string is assigned to FileName variable in Flow.

Test Result

Test Result

Now, let’s try sending the file from Postman and let’s look at the Flow to extract file content. In your Postman, choose File form-data and send the request.

Send the file from Postman

Send the file from Postman

Open the executed flow. This time, you will see ‘click to download’ in the output of HTTP request.

Test Result with file

Test Result with file

When you open it, you will see a massive output, but we are only after for a few things which are body and $content. $content is Base64 of uploaded file.

Multipart body content

Multipart body content

To get this content, add another variable initialiser. This time we are going to set its type as Object, as Google Drive accepts JSON.

Prepare file content

Prepare file content

Now, let’s add another action to upload a file to Google Drive. It will ask you to connect to Google if you have no prior connection.

Google Drive connector

Google Drive connector

Now, let’s choose the folder path in Google Drive, file name and its content. You will need to write an expression for file content to get the object of FileContent variable.

Google Create File action

Google Create File action

Save the Flow. Go back to Postman, and send the request. You will see the flow is executed and a file is uploaded to your Google Drive.

I will cover the process of converting this Flow into a custom connector and calling it directly from PowerApps, in Part 2.

Microsoft CRM Portal (online) development essentials

Published / by AK / Leave a Comment

After developing a custom portal on Microsoft CRM Portals, I like to share my experience.
This is kind of starter guide to build highly customised web pages on Microsoft CRM portals. It is a high level and very informal guide.

Libraries and frameworks

To customise the portal, a good understanding of followings are essential.

Bootstrap

Microsoft CRM portal uses Bootstrap. Use bootstrap customiser like https://www.bootstrap-live-customizer.com/ for a quick customisation.

Continue reading