Sunday 26 April 2020

Automate Microsoft Teams Integration with Dynamics 365, PowerApps and Portals


Introduction

Hello Everyone,

Welcome again to the Power Guide Mentorship Program.

I hope you and your loved ones are doing well and are in good health.

This pandemic and resulted isolation have made us turn to technology, to stay connected with our friends and colleagues in ways that we never imagined.

Almost overnight, video conferencing and digital collaboration have become a big part of our daily life and work. With COVID-19 continuing to impact people and countries around the world,  Every organization encouraging our teams to work from home as much as possible, as are many organizations in this region. And they expect this trend to continue across the world.







During this tough time, Microsoft's top priority is the health and safety of employees, customers, partners, and communities. And they are promoting and encouraging everyone to Microsoft Teams for all kinds of collaborations and communications use.

By making Microsoft Teams available to as many people as possible, Microsoft aims to support public health and safety by keeping teams connected while they work apart.

Everyone around the world is now working, learning, and connecting with colleagues, friends, and family through the power of technology. From kitchen tables to living room couches, and from home offices doubling as home schools—people are relying on Microsoft Teams to work and learn.

Businesses large and small are depending on Teams for mission-critical work. First responders are using Teams to communicate when lives depend on it. Governments are turning to Teams to move medical supplies to where they are needed most. Doctors and nurses are using it to consult with patients, and researchers are collaborating on it across continents to find a vaccine. And teachers are using Teams to teach students in entirely new ways. Important moments of human connection, achievement, and celebration have all moved online.

Hence, having a smooth Integration of Microsoft Teams with Microsoft Dynamics 365 and Power Platform is one of the most common requirement these days.

This article focuses on - Automate of Microsoft Teams Provisioning with various Microsoft and Non-Microsoft Products so that every user who is sitting at any corner in the world, could collaborate, connect, and communicate with each other online with ease.

Today, In this article I am going to share the information about the Automation of Microsoft Teams Provisioning and it's Integration with PowerApps and PowerApps Portal. 


Business Challenge

Let me first explain my business use case that pushed me to think about implementing this feature:

Being an Ambassador of 365 Saturday (World largest MVPs Community), we organize many training, webinars, and events worldwide. However, from the last few months due to the COVID-19 lockdown, we have been organizing these events online (almost every weekend) via Microsoft Teams.

Hence, being an Organizer or Admin of the Event, we all have pressure to organize and manage these events online in the most effective and efficient manner.


Since we are using Microsoft Teams for all online Events, We have been doing the following activities manually almost every weekend:

  • Create a new Team for a new Event.
  • Add all the Event Organizers and Admin as a Team Owner
  • Add all the Attendees as Guest Team Members (Outside or Internal Users)
  • Send a Team Invitation (Meeting) to all the participants along with the Event Schedule.
  • Remove/Delete the Team once the Event is finished (Optional).
Managing Teams within an Organisation for a specific project is an easy Job. Your Manager (being a Team Owner) needs to add only respective project members, However, just think, how tedious job it is when I have to create a Team and Add 500+ Participants manually, few of them need to be added on a request basis and all of these participants are not event part of your organization.

This made me think to design a reusable automate solution, which you can Plug and Play with any of the data source or power platform components like PowerApps, PowerApps Portals, Power Virtual Agent, Dynamics 365, Common Data Service, SharePoint, and many more...


Components and Technology Used
  • Microsoft Dynamics 365
  • Power Automate
  • PowerApps Portals/PowerApps
  • Microsoft Graph APIs
  • Azure Portal
  • Microsoft Graph Explorer

Pre-Requisites:
  • Dynamics 365 License/Trial
  • Power Automate License/Trial
  • Azure Subscriptions/Trial
  • Global Admin Rights on Azure Active Directory

High-Level Requirement and Configuration

D365 Configuration:
  • In Dynamics 365, I have Event, Organiser, and Attendee (Event Registration) Entities.
  • Event and Attendees have 1:N relation, which means an Event could have multiple attendees.
  • Organizer and Event have 1:N relation, which means one Organizer could host multiple events.
  • I have a Boolean field on Event - "Publish to Teams", which publish an event on PowerApps Portals and Automate Teams configuration in Microsoft Teams
  • I have a PowerApps Portal, which displays all the Events along with Event's Agenda, Speakers, and Registration option to allow Attendees to Register for a particular Event,


Business Requirement:
  • Once an Organiser Publish the Event (set Publish to Team field's value to true), a new Teams should get created in Microsoft Teams with the same name as Event Name.
  • The Organizer of that event should get added as the Owner of that Team.
  • And, all the Attendees of that Event should get added as a Guest Members of that Team,
  • Create a Team Meeting and Send the Meeting Invitation link to all the Event Participants.

Microsoft Teams Concepts

Before proceeding with solution design, I would like you to know a few fundamental concepts of Microsoft Teams, which is very useful from the developer perspective. Can have a look at this article.

  • Microsoft Teams allow anyone with a business or consumer email accounts, such as Outlook, Gmail, or others, can participate as a guest in Teams.
  • In order to add any Guest User (that doesn't belong to your organization) in Microsoft Teams, you can add them manually in Teams as well. however, to automate this process, these users need to be added in Azure AD as a Guest Users
  • Owner/Admin of the Team must be a licensed Azure AD User
  • Guest Team members are not necessarily to be a licensed Azure AD User. They could be Guest Azure AD Users as well.


  • As an admin, you can add a new guest user to the organization in a couple of ways.


    • Global admins or Teams admins and team owners add a guest to a team in the Teams clients or in the Teams admin center
    • Add guests to your organization through the Azure Active Directory (Azure AD) B2B collaboration.
  • By default, guest access is turned off. As the Office 365 admin, you must turn on guest access for Teams before the admin or team owners can add guests. Follow this article
  • Authorize Guest Access in Microsoft Teams, Follow this article

Solution Design

I have designed the Low Code - No Code solution using Power Automate, Microsoft Graph API and Azure

So a very high level we are going to perform the following tasks:

  • Azure AD - To Register an Azure Application, so that we can call and authenticate Microsoft graph API
  • Microsoft Graph API - To perform an operation in Azure AD and Microsoft Teams
    • Azure AD - Retrieve/Create and get Access Token of Azure AD User
    • Microsoft Teams - Create Team, Add Team Owner, Add Guest Team Member and Create Teams Meeting
  • Dynamics 365 -  Data Source, which will pass all relevant information to Power Automate, like Team Name, Team Owner, Team Members, etc
  • Power Automate -  Trigger on a particular event and Pull the information from Data Source (like D365) and automate the Team Creation, Adding Team Owner, Adding Team Members, and Send Team Invites to all participants

Here is a high-level Architecture of the same:




Let's get started...

Azure AD Configuration:

1.  Navigate to the Azure Portal.

2.  Search for App Registrations. Click App Registrations as shown below.



3.  Click on New Registration.



4.  Enter the Name and click Register.




5.  In the left panel, click Overview. Copy the Application (client) ID and Directory (tenant) ID values. These values will be used in Flow for authentication.




6.  In the left navigation, click Certificates & secrets. Click New client secret.





7.  Enter the description and set its Expiry to Never and click Add.




8.  Copy the secret value which will be used in flow for authentication.




9.  In the left navigation, click API Permissions.





10.  Click Add a permission. Select Microsoft Graph API as shown below.




11.  Click Application Permission and Add the following Permissions (Add permission based on your need). 


I have added the following Application and Delegate Permission based on my Requirements and the operations I need to perform using Microsoft Graph API.



12.  Click Grant admin consent.






Power Automate Configuration:

Since this is one of the most complex and key step of Team Configuration.

Let me first explain the Algorithm of complete logic, that I have converted to Power Automate.

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function CallPowerAutomate()
{

----Global Variable Initialization----

// Initialize few variables to store Azure AD configuration like clientid, secretkey and tenantid etc

// Initialize few more variables to store the value of HTTP JSON Response

For Example- We have to call Microsoft Graph API multiple times to create Team, to Add Member, to Add Owner, to retrieve the user from Azure AD, to create new users in Azure AD, etc.
In order to call Microsoft Graph API, we have to use HTTP requests in Power Automate. And get HTTP Response in JSON format. In order to store these JSON values, we need some additional variables to be initialized.


----Create Team----

// Using Microsoft Graph API - Create a new Team in Microsoft Team with default owner


----Add Attendees in Team as a Team Members----

Please Note - To add any user in Microsoft Team as a Guest User, the user needs to be present in Azure AD in the same tenant of Microsoft Teams.

There are basically two types of Azure AD Users

Member (Licensed) - User is licensed and active Member of Azure AD
Guest (Non-Licensed) - User is present in Azure AD as a Guest User, which doesn't need a license

Team Guest Member could be Member or Guest in Azure AD

// Retrieve all Attendees and Read each Attendee's Email Address
 Foreach(Attendees)
{
// Get Attendee Email Address 
// Perform Query in Azure AD using Microsoft Graph API to check whether any user of above Email Address present in AD or not

// if Present, then get the unique id of the user
// Add the user (Attendee) in the Team

// If not present, create a new user in Azure AD as a Guest User using Microsoft Graph API
// get the unique id of the user
// Add the user (Attendee) in the Team

}

----Add Organizer in Team as a Team Owner----

Please Note - To add any user in Microsoft Team as an Owner, that user needs to be present in Azure AD in the same tenant.

Team Owner must be a Member (Licensed User) in Azure AD. Guest cannot be added as Team Member

// Get Organiser Email Address 
// Perform Query in Azure AD using Microsoft Graph API to check whether any user of above Email Address present as a member or not

// if Present, then get the unique id of the user
// Add the user (Organiser) in the Team as a Team Owner

// If not present
// then do nothing, because we already added a default Owner while creating a new Team

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Power Automate Complete Steps (1 to 30)



Sub Steps of Step 26 (26-1 to 26-8)




Sub Steps of Step 26-7 (26-7-1 to 26-7-7)


Sub Steps of Step 29 (29-1 to 29-3)


Sub Steps of Step 30 (30-1 to 30-2)



Explanation of each Power Automate Step

// Step to Trigger Power Automate
1.When an Event Publish in Dynamics 365

// Step to Retrieve Organiser Email Address, We need the email id of an organizer to check whether a user of that email id already present in Azure AD or not
2. Get Organiser (custom entity - lookup on Event Entity) from Event Record
3. Get Contact Record (from Organiser record to read organizer Email Address

// Step to Initialize a few variables to store Azure AD Configurations and HTTP Response JSON values
4.Variable to Store Primary Owner of Teams (that we are going to create)
5.Variable to store Client Id, captured from Azure AD App
6.Variable to store Secret Key, captured from Azure AD App
7.Variable to store Directory (Tenant Id), captured from Azure AD App
8.Variable to store Attendee Email Address
9.Variable to store Guest User (Attendee) Guid already available in Azure AD
10.Variable to store Guest User (Attendee) Email already available in Azure AD
11.Variable to store JSON Body (use to add existing attendee in the team)
12.Variable to store JSON Body (use to add new attendee in the team)
13.Variable to store new Guest User (Attendee) Id created in Azure AD
14.Variable to store Type of Azure AD user, if he/she already present (Member/Guest)
15.Variable to store JSON Body (use to add organizer in Team)

// Call Microsoft Graph API using Power Automate HTTP Request to create a new Team. Also, Parse the HTTP JSON Response to retrieve newly created Team Id
16.Create a new Team with the same name as Event Name in Microsoft Team
17. Wait for Team to create, so delaying process for 30 seconds before performing the next step
18.Initialize Variable to Store newly created Team JSON response (store only location parameter from the whole response)
19.Initialize Variable to Store newly created Team Id from location parameter

// Call Microsoft Graph API using Power Automate HTTP Request to get Access Token. Authorization Token is one of the mandatory input parameters in order to Create a Microsoft Team meeting.
20.HTTP Request to Get Access Token
21.Parse HTTP JSON Response
22. HTTP Request to Create Team Meeting
23. Parse HTTP Response
24. Initialize Variable to Store Team Link (from joinURL parameter)

// We have used Two parallel branches (One Branch is to Retrieve all Attendees and add them in a newly created Team as a Guest Team member while Other Branch will be used to Retrieve the Organiser and add them as a Team Owner)

Left Branch:

// Retrieve all Attendees (participants) associated with an Event
//Read the email id of each Attendee.
//Find each Attendee Email id in Azure AD using Microsoft GraphAPI
//If the user is already present in AD, get the unique id of that user and add directly in Teams as a Team Member, 
//If not present, then first add the user in Azure Ad, get the newly created user id and then add it in Team as a Team Member
25. Use List Record Step to Read all Attendees associated with a Published Event
26. Add Apply to each control
  26-1 Use Apply to each, to read all retrieved attendee one by one
  26-2 Pass List Record Result (done  in 25) as an Input to Apply to each
  26-3 Use Get Record Step to get Email of Attendee
  26-4 Store the Attendee Email in a variable (initialize in step 8)
  26-4 HTTP Request to retrieve user information from Azure AD
  26-5 Parse the HTTP Request, JSON Response
  26-6 Store the ID, Email of User from JSON Response
  26-7 Add Condition Control
     26-7-1 Condition to Check, whether, the user is already present in AD
     26-7-2 If yes, Add the User directly in newly created Team
     26-7-3 If no, HTTP Request to Add the user in Azure Ad as a guest user
     26-7-4 Parse HTTP Request, JSON Response
     26-7-5 Store the JSON body to add the user in Team as a member
     26-7-6 Delay of 30 sec to make sure user is available in AD after creation
     26-7-7 Add the newly created Azure AD Guest User in Teams

// Send the Team Meeting Link to All Attendees
  26-8 Send the Team Meeting Link to Attendee

Right Branch:


// We already got the Organizer Email in Step 2 and 3
//Find Email id in Azure AD using Microsoft GraphAPI
//If the user is already present in AD, get the unique id of that user and add directly in Teams as a Team Owner, 

27. HTTP request to find Organiser in Azure AD
28. Parse JSON Response
29. Apply to each to read JSON value
  29-1 Pass Json Response as Input to Apply to each
  29-2 Store User Type in a variable (initialize in 14)
  29-3 Create JSON Body and Store it in in variable (initialize in 15) to Add the organizer in Team as a Team Owner in Later step
30 Add Condition Control
  30-1 Add Condition to check whether Organiser as an AD member present in AD.
  30-2 If Yes, then add organize as a Team owner in newly created Team

Microsoft Graph API

I know this article is a bit complex and hard to understand from a beginner's perspective. Because I have used so many Advanced features of Power Automate and other Azure components. But trust me, the intension of writing this article is not only to demonstrate the Power of Power Platform but also to showcase the capabilities of Microsoft Graph API, which is very useful nowadays in many requirements.

Let me explain some fundamental concepts of Microsoft Graph API...



What is Microsoft Graph API?

If we have to perform any operation in Dynamics 365 either from within the CRM Application like forms and views, through JavaScript, Plugin, Workflow, C# code, or through any language, Microsoft has given one Rest API called - Dynamics 365 WEB API (Enhanced version of Organisation Service or OData). And that API is only restricted to perform operations in Dynamics 365 only.

However, you already know that Microsoft Dynamics 365 is tightly coupled with numerous other Microsoft products and services like Microsoft Azure, Microsoft Teams, Office 365. Outlook, OneDrive, OneNote, Microsoft Excel, and many more. And we often need to interact with these products and services to fulfill various business needs.

Hence, in order to interact with all these products and services, Microsoft introduced a new Rest API called Microsoft Graph API, which enables you to access various Microsoft Cloud service resources.

Why we call this API as Graph API?

The Graph API is named after the idea of a "social graph" — a representation of the information on Facebook. It's composed of nodes — basically individual objects, such as a User, a Photo, a Page, or a Comment.

What are the capabilities of Microsoft Graph API?

Microsoft Graph exposes REST APIs and client libraries that provide a Gateway to access data on the following Microsoft 365 services:

  • Office 365 services: Delve, Excel, Microsoft Bookings, Microsoft Teams, OneDrive, OneNote, Outlook/Exchange, Planner, and SharePoint
  • Enterprise Mobility and Security services: Advanced Threat Analytics, Advanced Threat Protection, Azure Active Directory, Identity Manager, and Intune
  • Windows 10 services: activities, devices, notifications
  • Dynamics 365 Business Central


Are there any pre-requisites that need to be taken care of before consuming Microsoft Graph API?

  •  You need to have Azure Subscription
  • You need to Register an Application in Azure. Capture its ClientID, SecreTKey, and Tenant ID.
  • After you register your app and get authentication tokens for a user or service, you can make requests to the Microsoft Graph API.


Which language I can used to play with Microsoft Graph API?

Microsoft Graph API supports CORS, which means it is a Platform and Language-Independent API. Few languages that can be used to consume Microsoft Graph API are:

ASP.NET, C#, JAVA, Node JS, Android, Angular, Javascript, IOS, PHP, Python, React, Ruby, and many more.



What is the syntax of Microsoft Graph API?

Here is the syntax of Graph API-

{HTTP method} https://graph.microsoft.com/{version}/{resource}?{query-parameters}

Here,

HTTP method - GET, POST, PUT, PATCH, DELETE, etc
Version  - Microsoft Graph currently supports two versions: v1.0 and beta. The v1.0 version includes generally available APIs. Use the v1.0 version for all production apps. The beta includes APIs that are currently in preview.
Query Parameter - Same like you use the query parameter and query in ODATA and D365 Web API

For Example - Below is the syntax of Microsoft Graph API to retrieve Azure AD user by Email Address

GET https://graph.microsoft.com/v1.0/users?$select=id,mail&$filter=mail eq 'arpit@dynamics.community'


Any Tool, where I can test the Request and Response of Microsoft Graph API?

Microsoft Graph Explorer is a web-based tool that you can use to build and test requests using Microsoft Graph APIs. You can access Microsoft Graph Explorer at

 https://developer.microsoft.com/graph/graph-explorer.


Postman is also a tool that you can also use to build and test requests using the Microsoft Graph APIs. You can download Postman at

https://www.getpostman.com/

I would recommend going with Microsoft Graph Explorer, as it is more informative and user friendly from a troubleshooting perspective.


Can I consume Microsoft Graph API in Dynamics 365 Plugins, Custom Workflow, etc?

Yes, it is possible. Since Graph API can be consumed through C# code, therefore you can write the same logic in Plugin also.


Can we call Microsoft Graph API from PowerApps Portals? Tell me with Real-Time Example?

Yes, it is possible. You can call Microsoft Graph API from PowerApps and Dynamics 365 Portals.

You can pass Input Parameters from Portal to Power Automate. Power Automate can call the Graph API and return the response back to PowerApps Portals. (Can refer my previous article for this)

If your organization is restricted to use Power Automate, you can also use Plugin, C# Code or JavaScript to perform the operations.

 Real-Time Example -  In PowerApps Portal, Microsoft is planning to deprecate the Local Authentication feature and recommend to use Azure AD B2C as a default Portal Authentication option.

Azure AD B2C users are the Guest AD Users created in Azure Active Directory, which doesn't require an AD license

Now, In order to interact with these Azure AD B2C Users from Dynamics 365 or Portals, we don't have other option except Microsoft Graph API to perform the following activities:

  • To change the user's contact details in Azure like email, contact number, name, etc.
  • To automate the user creation in Azure AD from Dynamics 365 and Portal
  • To map existing D365 contacts with Azure AD B2C users.
  • To manage the Invitation process for Azure AD B2C users.
  • Automatically create username and password for Azure B2C users


Now, let's see how we have used Microsoft Graph API in Power Automate in our requirement

To Interact with Azure AD:

  • Retrieve Azure AD User details (like Unique Id, UserType, etc) by Email Address.
  • Create a Guest user in Azure AD, if the user is not already present.
  • Get Acces Token of Azure AD User

To Interact with Microsoft Teams:

  • Create a new Team in your Microsoft Teams
  • Add Team Owner (must be Azure AD Member, not Guest User)
  • Add Team Members (must be either Azure AD Member or Guest user)


Let's have a look, how we have consumed Microsoft Graph API in Power Automate

Retrieve User from Azure AD based on Email Address

Create a Guest User in Azure AD without sending an Invitation


Create a new Team with name - Power Guide Mentorship

Create a Team Meeting

Get Access Token of Azure AD User to authenticate Microsoft Graph API

Add Team Owner

Add Team Members as Guest Team Members




I hope this article helps you to Automate your Team's Provisioning.

That's all folks for today. Stay tuned for more updates. 

Stay Safe and Take Care !!

Cheers

Thursday 16 April 2020

PowerApps Portal - Perform CRUD Operation using Editable Subgrid





Introduction:

Hello Everyone,

Welcome to the Power Guide Mentorship Program.

Today, I am going to share a very useful TIP and Information regarding PowerApps Portal and Dynamics 365 Portal.

This article gives you the answers to the following questions:

  • Can we perform CRUD operation from Portal, without using Entity Forms and Entity List?
  • Can we design Editable Subgrid in Portal to Update the data directly in D365?
  • Can we Pass Input/Output Parameters between Portal and Dynamics 365?
  • Can we trigger Power Automate (replaced name of Microsoft Flow) directly from Portal?
I had these questions in my mind. However, I couldn't find any article on the internet which gives the answers to these questions. A lot of folks personally asked me about implementing these features in Dynamics 365 Portal. So, today at the end of this article, I promise you'll learn something really interesting...

Let us first discuss some complex business requirements of PowerApps Portal (Dynamics Portal).

Portal's Complex Business Requirement:

Requirement 1 - Display External System's Data on Portal - 
Several times, we get a requirement from the client to display an external system's or application's data on the portal. To do that, in most situations we need to consume the APIs and Web Services to retrieve the data from the external system and need to bind it into a Custom HTML Table.

Requirement 2 - Create a record in Dynamics 365 without using Entity Forms - 
I know this requirement gives a lot of pain to almost everyone who has worked with Portal in real-time projects. Because until now, there is no direct way available on Portal to Create the record without using Entity Forms.

Requirement 3 - Update the Dynamics 365 records without using Entity Form and Entity List - As of now the only way to update the existing records in Dynamics 365 is either Entity Form (to show the Entity Forms in Edit Mode) or Entity List, which allow you to update the record by either open the Entity Form in Edit Mode or open the record in a dialog to achieve the same.

Requirement 4 - Design a Custom HTML Table and Perform CRUD Operation - 
Most of the time, we have to compromise with Portal design, due to not having any options to Create/Update and Delete the records in Dynamics 365 except Entity Forms and Entity List.
For retrieval, we do have OData Query and Fetch XML options available. However, for Create/Update/Delete we only have Entity Forms and Entity Lists features are there.

Requirement 5 - Create an Editable Subgrid - 
I know, we have been using this feature in Dynamics 365 long back, however, we don't have such feature available in Portal. And we often end up pushing back such requirements, due to not having any custom way to perform CRUD operation from Portal.

Requirement 6 - Run Fetch XML On Demand and Change its execution order
We all know that Fetch XML is the best way available in Portal in order to pull the data from Dynamics 365. And, it is one of the most used features of Portal when it comes to the requirement where we have to design the portal page as per our need with Dynamics 365 data.
However, there are some limitations of Fetch XML:
  • It can only run on Page Load.
  • It cannot runs On-demand. Like on button click.
  • Its sequence/order is always first on the page. Means, it always runs at the beginning of the page load. We cannot change it's running order. For Example: If I have to run the Fetch XML once my particular business logic is completed, then it is not possible.
Requirement 7 - Pass Portal Parameters to perform complex Business Logic in Dynamics 365 -
Sometimes, we need to pass some information from Portal to CRM in order to perform some complex logic in Dynamics 365.
For Example- If I have a requirement to provide Approval functionality on the portal, where a specific set of users can approve the requests directly from the portal, And, in CRM we need to perform some complex business logic as soon as request status gets changed to Approved based on the user who Approved the request from Portal.
In this requirement, we could use the Entity List Workflow Action configuration, which lets you allow to run an on-demand workflow directly on Entity List's records. However, it doesn't provide any options to pass some information/parameters to the workflow. Like in our requirement, we need to pass the logged-in user id/name to know who approved the request.
Hence, we cannot implement such requirements directly from Portal and we end up writing either Plugin or Custom code to achieve this.

I know, there are many talented folks and portal experts out there, who might have got the solutions or alternatives to the above requirements. But, until now, I didn't get any concrete answers or solutions on the internet to implement these requirements with minimal coding and customization.

But today, I thought of combined all these requirements in a single requirement and demonstrate the solution of it.


Scope:

In today's article, I am going to create a Custom HTML Table which will provide the following features:
  1. Retrieve the Dynamics 365 Entity's data and Bind it into the Custom HTML Table.
  2. Create, Update and Delete the record in Dynamics 365.
  3. Editable Grid Feature, to update the record directly in D365 (same like Dynamics 365)
  4. Pass Input/Output Parameters to Dynamics 365 using Power Automate.
  5. Run Fetch XML On-Demand (button click)

Components:

In today's article, we are going to use the following components 
  • Dynamics 365
  • PowerApps Portal or Dynamics 365 Portal (of any type)
  • Power Automate (Microsoft Flow)
  • HTML/JavaScript/JQuery

Architecture:

The whole article revolves around these three components:

PowerApps Portal, Power Automate (Microsoft Flow) and Dynamics 365.

  • Portal Pass the information in the form of input parameters (JSON) to Dynamics 365 via Power Automate.
  • Dynamics 365 pass the information in the form Output Parameters (JSON) to Power Apps Portal via Power Automate




Pre-Requisites:
  • Dynamics 365 Instance
  • PowerApps Portal or Dynamics 365 Portal (of any type) 
  • Power Automate (Microsoft Flow)
  • HTML/JavaScript/JQuery Knowledge
Note: If you don't have the license of Dynamics 365 and Power Automate, you can test it on the D365 trial as well.


Implementation:

Step 1 - Create a Web Template and use it as WEB API

Through this step, we'll retrieve the data from Dynamics 365 Entity using Fetch XML and in a later stage will bind this data into a Custom HTML Table.

Step (a) Create a Web Template 

Step (b) Create a Fetch XML from Advance Find (whatever data you want to display on the portal)

Step (c) Paste the Fetch XML in Web Template between fetchxml liquid tag


{% fetchxml my_query %}

// Paste your Fetch XML downloaded from Advanced Find

{% endfetchxml %}


Step (d) Create a JSON structure of your fetch XML result as highlighted below:

{% fetchxml my_query %}
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
<entity name="lead">
<attribute name="subject" />
<attribute name="firstname" />
<attribute name="lastname" />
<attribute name="emailaddress1" />
<attribute name="mobilephone" />
<attribute name="leadid" />
<order attribute="fullname" descending="false" />
<filter type="and">
<condition attribute="createdon" operator="last-x-days" value="3" />
</filter>
</entity>
</fetch>
{% endfetchxml %}
{ "leads" :
[
{% for result in my_query.results.entities %}
{
"leadid":"{{result.leadid}}",
"subject" : "{{ result.subject }}",
"firstname" : "{{ result.firstname }}",
"lastname" : "{{ result.lastname }}",
"email" : "{{ result.emailaddress1 }}",
"phone" : "{{ result.mobilephone }}"
}
{% unless forloop.last %},{% endunless %}
{% endfor %}
]
}

In the highlighted JSON, All Bold texts are written after {{result. are the schema name of a CRM field. While the texts are written before the : (colon) are like variables, used to hold the field's value.


Step (e) Set the MIME TYPE to - application/json.  So that the Fetch XML result will return in JSON format.





Step (f) Create a Webpage along with Page Template





Step (g) Create an Entity Permission for the entity that you are using to retrieve the data in your Fetch XML. I have used Lead, therefore I have created Entity Permission for Lead Entity.
Associate appropriate Web Role to the Entity Permission (as per your requirement). I have associated Authenticated User Web Roles in my example.


Step (h) Test the JSON

Open the Webpage (partial URL) in the browser, you should get the entity data in JSON format (as shown below:





Step 2 - Create a Power Automate to communicate between Portal and Dynamics 365

Step (a) Create a Power Automate (Instant - From blank).

Step (b) Provide Name of the Flow and Choose When an HTTP request is received as Trigger Point




Step (c) Click on Use sample payload to generate the schema. Paste your sample JSON and Click on Done. Make sure there is no white space or syntax mistake in your sample JSON




My Sample JSON:

"lead" : [{ "Action":"Create", "RecordId":"123123", "Subject": "powerappsportal", "Firstname": "Arpit", "Lastname": "Shrivastava", "Email": "arpit@gmail.com"} ]}

In the above JSON, 



  • lead -  is a kind of variable inside my JSON which holds the whole JSON string.
  • Action - will hold the operation name like Create/Update/Delete, etc
  • RecordId - will hold the guid of dynamics 365 records. We'll pass null value when we have to Create the record, while in case of Update and Delete, we need to pass the guid of the record
  • Subject - hold subject of lead
  • Firstname - hold first name of the lead
  • Lastname - hold last name of the lead
  • Email - hold email address of the lead
You just need to put some sample values (except the Bold ones) in the JSON when you paste it in the Sample JSON Payload screen (shown above). However, in your code (mentioned in Step 2), you need to pass the actual dynamic values in order to perform your business logic.

Note: You can design and structure your JSON and it's parameters (like lead, action, recordid, subject, etc) as per your business need. However, your JSON structure should remain the same to avoid any syntax error.

Step (d) Add Next Step and Select Initialize Variable (rename it as per your need). And provide values as shown below. To set the value:

  • Click inside the Value input box, you'll see a small popup window next to it.
  • Click on Expressions Tab inside the popup window.
  • Paste -  triggerOutputs()['headers']['origin'] inside Expressions and Click OK
Note: triggerOutputs()['headers']['origin'] - To read the origin value from HTTP request's header. Origin always holds the information of the source from where the request is initiated. In our case, the source should always be portal. hence the origin value would be 'https://<portalname>.powerappsportals.com'

See below:
Open any Power Automate instance From Run History and You'll see the origin in HTTP Request Headers 


  • You will see the origin value set in your Value input box


Step (e) Add Next Step and Select Initialize Variable (rename it as per your need). Provide a Name and set it's Type to String (as shown below). Keep its value blank as of now. We'll set it's value later.



Step (f) Add Next Step and Select Apply to each
  • Click inside the box Select an output from the previous step, you'll see the same popup window next to the input box.
  • Choose the name of your JSON. In my example, the name of JSON is lead. (As shown below) Hence, it's showing a lead in the popup window
"lead" : [{ "Action":"Create", "RecordId":"123123", "Subject": "powerappsportal", "Firstname": "Arpit", "Lastname": "Shrivastava", "Email": "arpit@gmail.com"} ]}


  • We have to add the Conditions inside Apply to each as per the below diagram.


  • So let's get started and Add first Condition Step inside Apply to each Step. And add the following 2 conditions to it.
    • Action equal to 'Create' and
    • Origin contains '<your portal URL> or <portal domain>'




  • If Condition is True.
  • Add Dynamics 365 Action and Choose to Create a record step
  • Add one more step just below the Create a new record step and Choose Set Variable in order to set the variable (that we have initialized in Step (e)) value to Guid of the created record.
Expression: body('Create_a_new_record')['iteminternalid']


Note: iteminternalid is the key inside the JSON body of Create a new record step that holds the Guid of the newly created D365 record. In order to read this value we need to use the above expression.

Open any Power Automate instance From Run History and You'll see the iteminternalid in Create a new record step 




  • If Condition is False
  • Add one more Condition Step and again add following 2 conditions
    • Action equal to 'Update'
    • Origin contains '<your portal URL> or <domain>'
  • If Condition is True (Request is for Update and originated from Portal)
  • Add Dynamics 365 Action and Choose to Update a record step

  • If Condition is False
  • Add one more Condition Step and again add following 2 conditions
    • Action equal to 'Delete'
    • Origin contains '<your portal URL> or <portal domain>'
  • If Condition is True (Request is for Delete and originated from Portal)
  • Add Dynamics 365 Action and Choose to Delete a record step
  • A complete view of all the Conditions inside Apply to each step:



Step (g) Add Next Step outside Apply to each and Choose Response Step to capture HTTP Request Request. We don't need to read the response in case of Update and Delete. However, in the case of Create we need to return the Guid of created record as a response. Hence, we are using this step to Create operation only.

Complete View of Power Automate:


Complete View

Explanation of each Step



Step 3 - Webpage to Design Custom HTML Table

In this step, we'll design a Custom HTML Table and Bind the data retrieved from Fetch XML (Step 1)

Step (a) Create a new webpage as below



Step (b) Open the Localized Content record from the Webpage and Paste the code in Copy HTML Section (as shown below)

Download the complete code from GIT Hub



Let's understand the code

This code does the following Tasks:

Page Load -

  • It requests the Webpage URL (as a WEB API) which is associated with Web Template.
  • Retrieve the response in JSON format (as per the JSON structure defined in Step 1)
  • Parse the JSON.
  • Bind the JSON data in Custom HTML Table
  • Provides Update/Delete/Refresh options in each row.
  • Creates an HTML Form to Create the record in Dynamics 365.
  • Overall we are providing CRUD operation through Custom HTML Table

Retrieval

Code to call webpage (associated with web template) as WEB API to retrieve dynamics 365 data.
leadpage is the name of my webpage created in Step 1

I have used the following code on click of Refresh Icon, in order to refresh the table (if required) and get the updated data from Dynamics 365.

$(document).ready(function(){
$(".data-table").find($("tr")).slice(1).remove();
$.ajax({
cache: false,
type: 'GET',
url: '~/leadpage/',
dataType: 'json',
success: function (data) {
$.each(data, function (key, value)
{
var i;
for(i=0;i<value.length;i++){
//Write your logic to play with the data
}
});
}
});
});




Create

Following code, used to collect the information from Textbox Controls and Providing as Input Parameters to Power Automate in JSON format in order to create a record in Dynamics 365


$("#saveBTN").click(function(){

//JSON structure
var leadRecord = '{ "lead" : ['+
'{ "Action":"Create", "RecordId":"null",
"Subject": "' + name +'", "Firstname": "' + firstname +'",
"Lastname": "' + lastname +'", "Email": "' + email +'"} ]}';

//HTTP Request to Power Automate URL
var req = new XMLHttpRequest();
var url = "<Paste the URL, you copied it from Power Automate HTTP Request Step>";
//Send https request to Power Automate
req.open("POST", url, true);
req.setRequestHeader('Content-Type', 'application/json');
req.send(leadRecord);

req.onreadystatechange = function() {
if(req.readyState == XMLHttpRequest.DONE) {


//Get the record Guid as a Response from Power Automate

recordId = req.responseText;

alert("Record has been created...");
}
}
});

Fill the form and Save the Information

The information has been Saved in Dynamics 365 and Showing in HTML Table


Update

The following code used to Update the record in Dynamics 365 by providing the updated values as Input Parameters along with guid of the record to Power Automate in JSON format.

$("body").on("click", ".btn-update", function(){

//JSOn Structure
var leadRecord = '{ "lead" : ['+
'{ "Action":"Update","RecordId":"'+recordId+'",
"Subject": "' + name +'", "Firstname": "' + firstname +'",
"Lastname": "' + lastname +'", "Email": "' + email +'"} ]}';
alert(leadRecord);

//HTTP Request to Power Automate URL
var req = new XMLHttpRequest();
var url = "<Paste the URL, you copied it from Power Automate HTTP Request Step>";;
//send https request to Power Automate
req.open("POST", url, true);
req.setRequestHeader('Content-Type', 'application/json');
req.send(leadRecord);
alert("Record has been Updated...");
});

Update the Lastname from 'Shrivastava' to 'Consultant' by Providing Editable Subgrid Feature

The information has been updated successfully


Delete

The following code used to Delete the record from Dynamics 365 by providing the Guid of record as an Input Parameter to Power Automate in JSON format.

$("body").on("click", ".btn-delete", function(){

//JSON Structure
var leadRecord = '{ "lead" : ['+
'{ "Action":"Delete","RecordId":"'+recordId+'",
"Subject": "null", "Firstname": "null", "Lastname": "null", "Email": "null"} ]}';
//HTTP Request to Power Automate URL
var req = new XMLHttpRequest();
var url = "<Paste the URL, you copied it from Power Automate HTTP Request Step>";
//send https request to Power Automate
req.open("POST", url, true);
req.setRequestHeader('Content-Type', 'application/json');
req.send(leadRecord);
$(this).parents("tr").remove();
alert("Record has been Deleted");
});

Deleting the Record from the Table

The record has been deleted successfully

Refresh (Run Fetch XML on button click)-

Refresh the HTML table means, anytime we can refresh the table and can retrieve the updated data from Dynamics 365.

The code that we have written on-load of the page to retrieve the Lead data from Dynamics 365, can also be written on Refresh Button click as well so that we can the code on-demand as well.

So if you would have noticed that we are calling the Fetch XML as per our need and on button click that was one of the major limitations of using Fetch XML inside Web Template.

$("#refresh").click(function()
{
$(".data-table").find($("tr")).slice(1).remove();
$.ajax({
cache: false,
type: 'GET',
url: '~/leadpage/',
dataType: 'json',
success: function (data) {
$.each(data, function (key, value)
{
var i;
for(i=0;i<value.length;i++){
//Write your logic to play with the data
}
});
}
});
});


Download Complete Code:

You can find the complete code of the Custom HTML Table and Editable Subgrid from my GIT HUB Repository




Important Tips:


  • Don't copy the code from the article for the actual project's use as it may have some white spaces and special characters. You might end up facing unnecessary syntax issues if you do so. I have provided code in this article for understanding purposes only. If you want to get the actual code. Please download it from GIT HUB (given the links above).


  • For demonstration, I have used Lead Entity, declared/initialized various variables and Input/Output parameters. And refer the same throughout the code and in Power Automate. Please make sure to change the code/variables/parameters based on your requirements



That's all folks.

Stay Tuned for next interesting Tip - PowerGuideTip10
Blogger Widgets