Working as part of the PrioritZ fusion team you will be configuring a custom connector for a new API you build using Azure Functions. The team has decided to move the logic when a user creates a new “ask” to the Azure Function API. This will keep the Power App formula simple and allow more complex logic to be added in the future. In this lab, you will create the function, use the Dataverse API, and secure the API with Microsoft Entra ID configures a custom connector to use the API and changes the Power App to use the connector.
Note: This lab requires an Azure subscription (or trial) in the same tenant as your Dataverse environment.
- Exercise 1: Create Azure Function
- Exercise 2: Function implementation
- Exercise 3: Publish to Azure
- Exercise 4: Create Connector
- Exercise 5: Use Function from Canvas App
In this exercise, you install the Azure tools extension for Visual Studio Code and create the function
-
Start Visual Studio Code using the shortcut available on the desktop.
-
Select the Extensions tab.
-
Search for Azure tools (1) and click on Install (2) to install the Azure Tools extension.
-
Wait for the installation to complete.
-
You should now see the new Azure Tools extension you added.
-
Click on Terminal from the top menu and select New Terminal.
-
Run the below command in the terminal to create a new folder.
md ContosoFunctions
-
Select Azure Tools (1) from the left navigation menu and navigate to the Workspace (2) section.
-
Click on the shown symbol(1) in the image, under Workspace section, click Create Function (2), and click Create New Project.
Note: If the + symbol is not visible, select settings and see if there are any updates required for vscode and update the app Close the current vscode and open it again and perform the above step.
-
Select the ContosoFunctions (1) folder you created and click select Folder (2)
-
Now, you will be presented with the below pop-up, click on Yes to create a new project.
-
Select C# for language.
-
Select .NET 6.0 LTS for .NET runtime.
-
Select HTTP trigger with OpenAPI for template.
-
Enter CreateTopic for function name and hit [ENTER].
-
Enter Contoso.PrioritZ for namespace and hit [ENTER].
-
Select Anonymous for AccessRights. Later we will protect the function using Microsoft Entra ID.
-
If you are presented with the below window, select Open in the current window.
-
Your function should open in Visual Studio Code.
-
If you got a pop-up Do you trust authors of the files in this folder,Click on Yes, I trust the author
-
Click on Terminal from the top menu and select Run Build Task.
-
Once the build is succeeded, press any key to close the terminal.
In this exercise, you will implement the function.
-
Click New file that is next to ContosoFunctions to add a new file.
-
Name the new file Model.cs
-
Open the new Model.cs file and paste the code below. This will define the data that will be sent from the Power App.
using System; using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes; using Microsoft.OpenApi.Models; namespace Contoso.PrioritZ { public class TopicItemModel { public string Choice { get; set; } public string Photo { get; set; } } public class TopicModel { [OpenApiProperty(Nullable = false, Description = "This is a topic")] public string Topic { get; set; } public string Details { get; set; } public DateTime RespondBy { get; set; } public string MyNotes { get; set; } public string Photo { get; set; } public TopicItemModel[] Choices {get;set;} } }After adding the code your Model.cs will look like the below screenshot:
-
Open the CreateTopic.cs file.
-
Locate the Run method attributes (line numbers 24-27) that are present above the Run method and replace them with the attributes below. This provides user-friendly names when we create a connector to use the API.
[FunctionName("CreateTopic")] [OpenApiOperation(operationId: "CreateTopic", tags: new[] { "name" }, Summary = "Create Topic", Description = "Create Topic", Visibility = OpenApiVisibilityType.Important)] [OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)] [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(Guid), Description = "The Guid response")] [OpenApiRequestBody(contentType: "application/json", bodyType: typeof(TopicModel))]After adding the attributes your Run method should look like the below screenshot:
-
Remove get from the Run method as you should only have post.
-
Click on Terminal from the top menu and select the New Terminal.
-
Run the below command in the terminal to add the Power Platform Dataverse Client package.
dotnet add package Microsoft.PowerPlatform.Dataverse.Client -
Wait for the package to be added then run the below command to add the Azure Identity package.
dotnet add package Azure.Identity -
Wait for the Azure Identity package to be added.
-
Open the CreateTopic file and add the statements below after line number 11.
using System; using Microsoft.Identity.Client; using Azure.Core; using Azure.Identity; using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums; using Microsoft.Xrm.Sdk; -
Add the below method after the Run method. This method will use the token passed from the calling app to get a new token that will allow the function to use the Dataverse API on behalf of the calling user.
public static async Task<string> GetAccessTokenAsync(HttpRequest req,string resourceUri) { //Get the calling user token from the request to use as UserAssertion var headers = req.Headers; var token = string.Empty; if (headers.TryGetValue("Authorization", out var authHeader)) { if (authHeader[0].StartsWith("Bearer ")) { token = authHeader[0].Substring(7, authHeader[0].Length - 7); } } string[] scopes = new[] {$"{resourceUri}/.default" }; string clientSecret = Environment.GetEnvironmentVariable("ClientSecret"); string clientId = Environment.GetEnvironmentVariable("ClientID"); string tenantId = Environment.GetEnvironmentVariable("TenantID"); var app = ConfidentialClientApplicationBuilder.Create(clientId) .WithClientSecret(clientSecret) .WithAuthority($"https://login.microsoftonline.com/{tenantId}") .Build(); //Get On Behalf Of Token for calling user UserAssertion userAssertion = new UserAssertion(token); var result = await app.AcquireTokenOnBehalfOf(scopes, userAssertion).ExecuteAsync(); return result.AccessToken; } -
Replace the code inside the Run method with the code below. This will provide an instance of the Dataverse API and use the GetAccessToken function we just defined.
_logger.LogInformation("Starting Create Topic"); var serviceClient = new ServiceClient( instanceUrl: new Uri(Environment.GetEnvironmentVariable("DataverseUrl")), tokenProviderFunction: async uri => { return await GetAccessTokenAsync(req, Environment.GetEnvironmentVariable("DataverseUrl")); }, useUniqueInstance: true, logger: _logger); if (!serviceClient.IsReady) { throw new Exception("Authentication Failed!"); } -
Add the following code after the if statement of the Run method to reserialize the request. This will get us the data passed from the caller.
string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); var data = JsonConvert.DeserializeObject<TopicModel>(requestBody); -
Add the below code that creates the row to the Run method after the code you added in the previous step to reserialize the request. This code creates the rows in Dataverse is where we might add more logic in the future.
var ask = new Entity("contoso_prioritztopic"); ask["contoso_topic"] = data.Topic; ask["contoso_details"] = data.Details; ask["contoso_mynotes"] = data.MyNotes; ask["contoso_respondby"] = data.RespondBy.Date; if (data.Photo != null) { // Remove unnecessary double quotes, // Remove everything before the first comma (embedded stuff) ask["contoso_photo"] = Convert.FromBase64String(data.Photo.Trim('\"').Split(',')[1]); } var topicId = await serviceClient.CreateAsync(ask); foreach (var choice in data.Choices) { var item = new Entity("contoso_prioritztopicitem"); item["contoso_choice"] = choice.Choice; item["contoso_prioritztopic"] = new EntityReference("contoso_prioritztopic", topicId); if (choice.Photo != null) { item["contoso_photo"] = Convert.FromBase64String(choice.Photo.Trim('\"').Split(',')[1]); } var choiceId = await serviceClient.CreateAsync(item); } -
Add the code below to the Run method to return the topic ID as JSON (required by Power Apps) after the code you added in the previous step to create the row to the Run method.
return new OkObjectResult(topicId); -
Click Terminal (1) and select Run Build Task (2).
-
The run should succeed. Press any key to stop.
Note :
- If the build task operation fails with the errors, please make sure that you have followed the previous instructions and added the code correctly in CreateTopic.cs and Model.cs files.
- Additionally you can find the CreateTopic.cs and Model.cs files in the location C:\LabFiles, you can compare your code with these files and fix the issues if there are any then try to perform step 17 again.
In this exercise, you will deploy the function to Azure.
-
Select Azure Tools from the left-hand side menu.
-
Click Sign in to Azure under Resources section.
-
Complete the Sign-in process using the below credentials.
- Email/Username:
- Password:
-
Close the sign-in browser window once the sign-in process is completed.
-
Navigate back to Visual Studio Code and click on + that is next to your Resources tab to create a new Function App.
-
Now, search for and select Create Function App in Azure.
-
Enter PrioritZFunc for function app name and hit [ENTER].
-
Select .NET 6(LTS) In-process.
-
Select the location: from the list and wait for the Function App to be deployed.
-
Once the Function App is deployed, Click Deploy to Azure under the Workspaces section and choose the Function App you created.
-
Wait for the function app to be deployed then navigate to Azure Portal using the below URL.
https://portal.azure.com/ -
Select All resources, search for the function app PrioritZFunc that you have deployed earlier and click to open it.
-
Select Authentication (1) from the left hand side menu and click on Add identity provider (2).
-
Select Microsoft for Identity provider and Current tenant - Single tenant for Supported Account types then click on Add.
-
Open the Portal menu by clicking on the Portal menu icon.
-
Select Microsoft Entra ID from the list of resources.
-
Select App registrations under Manage from the left hand side menu.
-
Click to open the PrioritZFunc to open the app.
-
Copy the Application (client) ID of the PrioritZFunc application registration and keep it on a notepad as PrioritZFL API application ID. You will need this ID in future steps. This ID will be used to configure the protection of the API.
Note: Make sure to copy and paste the correct Application (client) ID value. Copying the incorrect value will result in issues in the next steps/tasks.
-
Copy the Directory (tenant) ID and keep it on a notepad as Tenant ID. You will need this ID in future steps.
Note: Make sure to copy and paste the correct Directory (tenant) ID value. Copying the incorrect value will result in issues in the next steps/tasks.
-
Select Certificates & secrets under Manage from the left hand side menu.
-
Click + New client secret.
-
Provide a description as PrioritZ API secret(1), select 3 months(2) , and click Add(3).
-
Copy the Value and keep it in a notepad as PrioritZFL API Secret. You need this value in future steps.
Note: Make sure to copy and paste the correct Secret value. Copying the incorrect value will result in issues in the next steps/tasks.
-
Select API permissions under Manage from the left hand side menu.
-
Click + Add a permission.
-
Select Dynamics CRM from the list of API permissions. Dynamics CRM is Dataverse, the Azure portal just hasn’t been updated as of the time of the writing of these steps.
-
Check the user_impersonation checkbox and click Add permission.
-
Go back to Home and open the PrioritZFunc function app.
-
Select Environment Variables (1) under Settings from the left hand side menu..
-
Click + Add (2)
-
Enter the following details on the Add/Edit application setting blade and click Apply (3).
- Name: ClientID (1)
- Value: Paste the PrioritZFL API application ID (2) that you have noted earlier in the notepad.
-
Click + Add again.
-
Enter the following details on the Add/Edit application setting blade and click Apply (3).
- Name: ClientSecret (1)
- Value: Paste the PrioritZFL API Secret (2) that you have noted earlier in the notepad.
-
Click + Add again.
-
Enter the following details on the Add/Edit application setting blade and click Apply (3).
- Name: TenantID (1)
- Value: Paste the TenantID (2) that you have noted earlier in the notepad.
-
Start a new browser window or tab navigate to the Power Platform admin center and select Environments.
https://admin.powerplatform.microsoft.com/environments -
Click to open the Dev environment named DEV_ENV_ you are using for this lab.
-
Copy the Environment URL and paste it into the notepad.
-
Click + Add one more time.
-
Enter the following details on the Add/Edit application setting blade and click Apply.
- Name: DataverseURL
- Value: Paste the Environment URL that you have noted earlier in the notepad.
Note: Make sure to paste the correct Environment URL that you noted earlier in this task. Copying the incorrect value will result in issues in the next steps/tasks.
-
You should see the four application settings you added.
-
Click Apply and In Save changes pop up click on Confirm.
-
Paste the below URL in Notepad and replace
{tenant id}and{api app id}with tenant id and PrioritZFL API application ID values from your notepad.https://login.microsoftonline.com/{tenant-id}/adminconsent?client_id={api app id}After updating the values, your URL should look like this:
https://login.microsoftonline.com/2140cxxxxxxx/adminconsent?client_id=195b2axxxxxxx -
After updating the values, navigate to the URL in a browser tab and sign in with the below credentials.
- Email/Username:
- Password:
- Click Accept.
-
Navigate to the Azure portal, then search for Microsoft Entra ID (1) in the search bar and select Microsoft Entra ID (2) from the suggestions.
-
Select App registrations (1) from the side blade and click on + New registration (2). This application registration will be used for the connector to access the protected API.
-
Please provide the following details and click on Register (5).
- Name: PrioritZConnector (1)
- Supported account types: Accounts in this organizational directory only (TenantName only - Single tenant) (2)
- Redirect URL: Select Web (3) and provide
https://global.consent.azure-apim.net/redirect(4) as the URL.
-
Copy the Application (client) ID and save it in a notepad as PrioritZ Connector application ID.
-
Select Certificates & secrets from the side blade and click on + New client secret.
-
Provide PrioritZsecret (1) as description, set expiry to 3 months (2), and click on Add (3).
-
Copy the Secret value and save it in a notepad as PrioritZ Connector secert.
-
Select API permissions (1) from the side blade and click on + Add a permission (2).
-
In the Request API Permissions tab, select the My APIs (1) tab and select PrioritZFunc (2).
-
Toggle the user_impersonation (1) checkbox and click Add permission (2).
In this exercise, you will create a new custom connector.
-
Navigate to Azure Portal using the below URL.
https://portal.azure.com/ -
Now in the Azure portal, click on Resource Groups present under Navigate.
-
Select the prioritzfunc resource Group from the list.
-
Select PrioritZFunc function resource from the list.
-
From the overview page, Copy the URL of the function.
-
Add /api/swagger.json to the end of the URL and access it using the browser.
Note: If permissions prompt pops up, Click on Accept and continue.
-
Right-click on the swagger select Save as and Save the file in your local machine-Provide a name to file as swag.json.
-
Navigate to the Power Apps maker portal by using the below URL. Make sure the development environment is selected.
https://make.powerapps.com -
Expand Dataverse (1) and select Custom Connectors (1).
-
Click on the chevron button next to the New custom connector and select Import an OpenAPI file.
-
Enter PrioritZ Connector (1) for name and click Import (2).
-
Select the swagger file (1) which you saved in step 7 of this task and Click Continue (2).
-
Provide PrioritZ Connector (1) as description as and click on Security (2).
-
Select OAuth 2.0 (1) for Authentication type. Provide the following details and Click on Create connector (8).
- Identity Provider: Azure Active Directory (2)
- Client id: Paste PrioritZ Connector application ID (3) which you copied earlier
- Client secret: Paste PrioritZ Connector Secret (4) which you copied earlier
- Tenant ID: Paste the Tenant ID (5) which you copied earlier
- Resource URL: Paste PrioritZ API application ID (6) which you copied earlier
- Enable on-behalf-of login: true (7)
-
Now navigate to the connecter you just created and click on the edit button. Select the Test (1) tab from the drop down menu and click + New connection (2).
-
Click on Create.
-
If the login prompt pops up enter the below credentials and click on Accept to accept the terms.
- Email/Username:
- Password:
-
Once the connector is created, select Custom connectors (1) from the left side menu and click Edit (2) on the PrioritZ connector.
-
Select the Test from the drop-down menu tab.
-
Make sure the connection you created is selected.
-
Turn on Raw Body and provide the JSON below and click Test operation.
{ "topic": "Test Topic", "details": "From Azure Function", "respondBy": "2022-11-01", "myNotes": "It worked", "choices": [ { "choice": "Choice 1" } ] } -
The operation test should succeed, and the response should look like the image below.
In this exercise, you will use the Azure function you created via the custom connector from the PrioritZ Admin canvas application.
-
Navigate to the Power Apps maker portal and make sure you are in the correct environment.
-
Select Apps, select the PrioritZ Admin application and click Edit.
-
Select Data , click + Add data , search for prioritz connector, and select the PrioritZ Connector you created.
-
Add the connector by clicking on it again.
-
Click on the ... More actions button of the connector you just added and select Rename.
-
Rename the connector PrioritZFunction.
-
Select the Tree view and expand the Add Topic Screen.
-
Select the Add choice icon.
-
Replace the OnSelect formula of the Add choice icon with the formula below. This adjusts the column names to match the API and encodes the photos.
Collect( colAddChoices, { choice: 'Choice name textbox'.Text, photoRaw: UploadedImage1.Image, photo: JSON( UploadedImage1.Image, JSONFormat.IncludeBinaryData ) } ); Reset('Choice name textbox'); Reset(AddMediaButton2) -
Select Save topic icon.
-
Replace the OnSelect formula of the Save topic icon with the formula below. This changes to have the API create the “ask”.
Set(returnGuid, PrioritZFunction.CreateTopic({ topic: 'Topic name textbox'.Text, details: 'Topic details textbox'.Text, respondBy: 'respond by date picker'.SelectedDate, myNotes: 'Notes textbox'.Text, photo: JSON(AddTopicImage.Image, JSONFormat.IncludeBinaryData), choices: ShowColumns(colAddChoices, "choice", "photo") })); Notify("Topic created! " & returnGuid, NotificationType.Success, 5000); Back(); -
Click Save.
-
Click Publish.
-
Select Publish this version and wait for publishing to complete.
-
Do not navigate away from this page.
-
Select the Home Screen and click Preview the app.
-
Click on the + add button.
-
Enter Function Test for Topic, Testing the function for Details. Note for testing the function for Note, select a date for Response by, and click add a picture.
-
Navigate to this path C:\LabFiles in file explorer, select image.png and click open.
-
Enter Test choice one for Choice and click add a picture.
-
Navigate to this path C:\LabFiles in file explorer, select image.png and click +.
-
Enter Test choice two for Choice and click add a picture.
-
Navigate to this path C:\LabFiles in file explorer, select image.png and click +.
-
Click Save.
-
The new topic should be saved, and you should be navigated back to the main screen.
-
Locate the new topic you created and open it.
-
You should see the two choices you added to the topic.
In this lab , you learned to create, implement, and publish an Azure Function, create a connector for it, and test its integration within Power Platform apps.



.png)
.png)







.png)


.png)
.png)

.png)


.png)
.png)
.png)























.png)
.png)
.png)

.png)


.png)

u.png)




.png)

.png)














.png)













.png)
.png)
.png)
.png)
.png)

.png)
.png)
.png)

.png)
.png)
.png)
.png)

