Building a Cloud-Native Power Apps ALM Pipeline with GitLab, Google Cloud Build and PAC CLI: Streamlining Solution Lifecycle Automation

A unique combination to achieve deployment automation of Power Platform Solutions

Hi Folks,

This post is about ALM in Power Platform integrating with a different ecosystem than usual, i.e. using Google Cloud, sounds interesting..? This approach is mainly intended for folks using Google Cloud or GitLab as part of their implementation.

Integrating Google Cloud Build with Power Platform for ALM (Application Lifecycle Management) using GitLab is feasible and beneficial. This integration combines GitLab as a unified DevOps platform with Google Cloud Build for executing CI/CD pipelines, enabling automated build, test, export, and deployment of Power Platform solutions efficiently. This was the core idea for my session on Friday 28 November, at New Zealand Business Applications Summit 2025.

Detailed Steps for this implementation

Create an access token in GitLab for API Access and Read Access

Click on Add new token, you can select at the minimum the below scopes while you were working with CI-CD using GitLab

Create a host connection for the repository in GitLab

Specify the personal access token created in the previous step

Link your repository

The created host connections in the previous step will be shown under Connec ctions drop down

Create Trigger in Google Cloud Build

Click on Create trigger above, provide a name, select a nearest region

Event:

For now, I am choosing Manual invocation for illustration

Specify where the name of the Repository where your YAML in GitLab resides

You can optionally specify the substitution variables which are nothing but parameters you can pass to your pipeline from Google Cloud Build Configuration

You can optionally give this for any approval and choose the service account tagged to your google account in the drop down.

Click on Save.

Next proceed to GitLab YAML

You can find the full code below

steps:
– id: "export_managed"
name: "mcr.microsoft.com/dotnet/sdk:9.0"
entrypoint: "bash"
args:
– "-c"
– |
echo "=== 🏁 Starting Export Process ==="
# ✅ Define solution name from substitution variable
SOLUTION_NAME="${_SOLUTION_NAME}"
# ✅ Install PAC CLI
mkdir -p "${_HOME}/.dotnet/tools"
dotnet tool install –global Microsoft.PowerApps.CLI.Tool –version 1.48.2 || true
# Add dotnet global tools dir to the shell PATH for this step/session (preserve existing PATH)
export PATH="$_PATH:${_HOME}/.dotnet/tools"
echo "=== 🔐 Authenticating to Power Platform Environment ==="
pac auth create –name "manual" –url "https://ecellorsdev.crm8.dynamics.com" –tenant "XXXXX-XXXX-XXXXX-XXXXXX-XXXXX" –applicationId "XXXXXXXXXXXXXX" –clientSecret "XXXXXXXXXXXXXXXX"
pac auth list
echo "=== 📦 Exporting Solution: ${_SOLUTION_NAME} ==="
pac solution export \
–name "${_SOLUTION_NAME}" \
–path "/tmp/${_SOLUTION_NAME}.zip" \
–managed true \
–environment "${_SOURCE_ENV_URL}"
echo "=== ✅ Solution exported to /tmp/${_SOLUTION_NAME}.zip ==="
echo "=== 🔐 Authenticating to Target Environment ==="
pac auth create \
–name "target" \
–url "https://org94bd5a39.crm.dynamics.com" \
–tenant "XXXXXXXXXXXXXXXXXXXXXXXX" \
–applicationId "XXXX-XXXXX-XXXXX-XXXXXX" \
–clientSecret "xxxxxxxxxxxxxxxxxxxx"
echo "=== 📥 Importing Solution to Target Environment ==="
pac solution import \
–path "/tmp/${_SOLUTION_NAME}.zip" \
–environment "${_TARGET_ENV_URL}" \
–activate-plugins \
–publish-changes
echo "=== 🎉 Solution imported successfully! ==="
options:
logging: CLOUD_LOGGING_ONLY
substitutions:
_SOLUTION_NAME: "PluginsForALM_GitLab"
_SOURCE_ENV_URL: "https://org.crm.dynamics.com"
_TARGET_ENV_URL: "https://org.crm.dynamics.com"
_TENANT_ID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
_CLIENT_ID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
_CLIENT_SECRET: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
_SOLUTIONS_DIR: "/workspace/Plugins/08112025"
view raw GitLabDemo.yaml hosted with ❤ by GitHub

Solution from Source Environment

Now lets run the trigger which will export the solution from the source environment and import to the target environment….we have manual trigger, automatic trigger whenever there is an commit to the repo in GitLab etc., you may pick whatever suits your needs best.

Solution imported to the target environment using Google Cloud Build

The below table illustrates key differences between Google Cloud Build and Azure Devops….

AspectGoogle Cloud BuildAzure DevOps Build Pipelines
Pricing ModelPay-as-you-go with per-second billingPer-minute billing with tiered pricing
Cost OptimizationSustained use discounts, preemptible VMsReserved capacity and enterprise agreements
Build EnvironmentServerless, container-native, managed by Google CloudRequires self-hosted or paid hosted agents
Free TierAvailable with build minutes and creditsAvailable but more limited
Operational OverheadLow, no need to manage build agentsHigher, managing agents or paying for hosted agents
Ideal ForVariable, short, or containerized workloadsLarge Microsoft-centric organizations
Integration Cost ImpactTightly integrated with Google Cloud serverless infrastructureIntegrated with Microsoft ecosystem but may incur additional licensing costs

Conclusion:

PAC CLI is a powerful command-line tool that automates authentication, environment, and solution management within Power Platform ALM, enabling consistent and repeatable deployment workflows. It integrates smoothly with DevOps tools like GitLab and Google Cloud Build, helping teams scale ALM practices efficiently while maintaining control and visibility over Power Platform environments. Just note, my intention was showcase the power of PAC CLI with wider ecosystem, not only with Microsoft.

Cheers,

PMDY

Enhancing Dataverse Plugins with Bulk Message Operations

Well, this could be a very interesting post as we talk about optimizing the Dataverse performance using bulk operation messages and too using Dataverse plugin customizations but wait, this post is not complete because of an issue which I will talk later in the blog. First let’s dig into this feature by actually trying out. Generally, every business wants improved performance for any logic tagged out to out of box messages and so developers try to optimize their code in various ways when using Dataverse messages.

Firstly, before diving deeper into this article, let’s first understand the differences between Standard and Elastic tables, if you want to know a bit of introduction to elastic tables which were newly introduced last year, you can refer to my previous post on elastic tables here.

The type of table you choose to store your data has the greatest impact on how much throughput you can expect with bulk operations. You can choose out of two types of tables in Dataverse, below are some key differences you can refer to: 

 Standard TablesElastic Tables
Data StructureDefined SchemaFlexible Schema
Stores data in Azure SQLStores data in Azure Cosmos DB
Data IntegrityEnsuredLess Strict
Relationship modelSupportedLimited
PerformancePredictableVariable, preferred for unpredictable and spiky workloads
AgilityLimitedHigh
PersonalizationLimitedExtensive
Standard and Elastic Table Differences

Plugins:

With Bulk Operation messages, the APIs being introduced are Create MultipleUpdateMultiple,DeleteMultiple (only for Elastic tables), Upsert Request(preview). As of now you’re not required to migrate your plug-ins to use CreateMultiple and Update Multiple instead of Create and Update messages. Your logic for Create and Update continues to be applied when applications use CreateMultiple or UpdateMultiple

This is mainly done to prevent two separate business logics for short running and long duration activities. So, it means Microsoft have merged the message processing pipelines for these messages (Create, Create Multiple; Update, Update Multiple) that means Create, Update messages continue to trigger for your existing implemented scenarios, when you update to use Create Multiple, Update Multiple still the Create, Update will behave.

Few points for consideration:

  1. While I have tested and still could see IPluginExecutionContext only provides the information and still I have noted Microsoft Documentation suggests using IPluginExecutionContext4 for Bulk Messages in Plugins where it is being shown as null yet.
  2. While you were working with Create, Update, Delete, you could have used Target property to get the input parameters collection, while working with Bulk Operation messages, you need to use Targets instead of Target.
  3. Instead of checking whether the target is Entity you need to use Entity Collection, we need to loop through and perform our desired business logic
  4. Coming to Images in plugin, these will be retrieved only when you have used IPluginExecutionContext4.

Below is the image from Plugin Registration Tool to refer(e.g. I have taken UpdateMultiple as reference, you can utilize any of the bulk operation messages)

Sample:

Below is the sample, how your Bulk operation message plugin can look like…you don’t need to use all the contexts, I have used to just check that out.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Crm.Sdk;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
namespace Plugin_Sample
{
public class BulkMessagePlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IPluginExecutionContext2 context2 = (IPluginExecutionContext2)serviceProvider.GetService(typeof(IPluginExecutionContext2));
IPluginExecutionContext3 context3 = (IPluginExecutionContext4)serviceProvider.GetService(typeof(IPluginExecutionContext3));
IPluginExecutionContext4 context4 = (IPluginExecutionContext4)serviceProvider.GetService(typeof(IPluginExecutionContext4));
ITracingService trace = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
// Verify input parameters
if (context4.InputParameters.Contains("Targets") && context.InputParameters["Targets"] is EntityCollection entityCollection)
{
// Verify expected entity images from step registration
if (context4.PreEntityImagesCollection.Length == entityCollection.Entities.Count)
{
int count = 0;
foreach (Entity entity in entityCollection.Entities)
{
EntityImageCollection entityImages = context4.PreEntityImagesCollection[count];
// Verify expected entity image from step registration
if (entityImages.TryGetValue("preimage", out Entity preImage))
{
bool entityContainsSampleName = entity.Contains("fieldname");
bool entityImageContainsSampleName = preImage.Contains("fieldname");
if (entityContainsSampleName && entityImageContainsSampleName)
{
// Verify that the entity 'sample_name' values are different
if (entity["fieldname"] != preImage["fieldname"])
{
string newName = (string)entity["fieldname"];
string oldName = (string)preImage["fieldname"];
string message = $"\\r\\n – 'sample_name' changed from '{oldName}' to '{newName}'.";
// If the 'sample_description' is included in the update, do not overwrite it, just append to it.
if (entity.Contains("sample_description"))
{
entity["sample_description"] = entity["sample_description"] += message;
}
else // The sample description is not included in the update, overwrite with current value + addition.
{
entity["sample_description"] = preImage["sample_description"] += message;
}
}
}
}
}
}
}
}
}
}

I have posted this question to Microsoft regarding the same to know more details on this why the IPluginExecutionContext4 is null , while still I am not sure if this is not deployed to my region, my environment is in India.

Recommendations for Plugins:

  • Don’t try to introduce CreateMultiple, UpdateMultiple, UpsertMultiple in a separate step as it would trigger the logic to be fired twice one for Create operation and another for CreateMultiple.
  • Don’t use batch request types such as ExecuteMultipleRequest, ExecuteTransactionRequest, CreateMultipleRequest, UpdateMultipleRequest, UpsertMultipleRequest in Plugins as user experiences are degraded and timeout errors can occur.
  • Instead use Bulk operation messages like CreateMultipleRequestUpdateMultipleRequest, UpsertMultipleRequest
  • No need to use ExecuteTransactionRequest in Synchronous Plugins as already they will be executed in the transaction.

Hope this guidance will help someone trying to customize their Power Platform solutions using Plugins.

I will write another blog post on using Bulk operation messages for Client Applications…

Cheers,

PMDY

Another way to install Plugin Registration Tool for Power Apps Developers from Nuget

Hi Folks,

Are you a Power Platform or Dynamics 365 CE Developer, you would definitely need to work on Plugin Registration tool at any given point of time and having a local application for Plugin Registration tool greatly helps…in this post, I will show a little different way to install Plugin registration tool and that too very easily.

Well, this approach is especially useful to me when I got a new laptop and need to work on Plugin Registration Tool where the Plugins already build for the implementation.

First 3 ways might have known to everyone through which you can download Plugin registration tool…do you know there is fourth approach as well…

  1. From XrmToolBox
  2. From https://xrm.tools/SDK
  3. Installation from CLI
  4. See below

Because there were limitations to use these approaches at least in my experience, I found the fourth one very useful.

  1. XrmToolBox – Not quite convenient to profile and debug your plugins
  2. https://xrm.tools/SDK – Dlls in the downloaded folder will be blocked and would need to manually unblock the DLL’s for the Tool to work properly
  3. CLI – People rarely use this.

Just do note that the approach is very easy and works only if you have a Plugin Project already. Please follow the steps below

  1. Just open the Plugin project.
  2. Right click on the solution and choose manage Nuget Packages for the solution
  3. Search for Plugin Registration tool as below

4. Choose the Plugin project and click install, confirm the prompt and agree the license agreement shown

5. Once installed, next go to the Project folder in the local machine.

6. Navigate to Packages folder, you should see a folder for Plugin Registration tool below

7. There you go, you can open the Plugin Registration Application under tools folder. You can undo the changes for the Assembly it is linked to Source control.

That’s it, how easy it was? Hope this would help someone.

Cheers,

PMDY

Triggers not available in Custom Connectors – Quick Review

Power Platform folks rarely build new custom connectors in a project, while most of them work on existing ones, it is often observed that the triggers are missing from the custom connector, below are the steps you can review if so…

1. Wrong Portal

If you’re building the connector in Power Apps, you won’t see trigger options. ✅ Fix: Use the Power Automate portal to define and test triggers. Only Power Automate supports trigger definitions for custom connectors.

2. Trigger Not Properly Defined

If your OpenAPI (Swagger) definition doesn’t include a valid x-ms-trigger, the trigger won’t appear.

Fix:

  • Make sure your OpenAPI includes a webhook or polling trigger.
  • Example:json"x-ms-trigger": { "type": "Webhook", "workflow": true }

3. Connector Not Refreshed

Sometimes, even after updating the connector, the UI doesn’t refresh.

Fix:

  • Delete and re-add the connector in your flow.
  • Or create a new connection in Power Automate to force a refresh.

4. Licensing or Environment Issues

If you’re in a restricted environment or missing permissions, triggers might not be available.

Fix:

  • Check if your environment allows custom connectors with triggers.
  • Ensure your user role has permission to create and use custom connectors.

5. Incorrect Host/Path in Swagger

If the host or path fields in your Swagger are misconfigured, the connector might fail silently.

Fix:

  • Ensure the host and path are correctly defined.
  • Avoid using just / as a path — use something like /trigger/start instead.

5. Incorrect Environment

Make sure you were in the right environment of the Power Platform, sometimes when juggling things around, we often mistakenly try using connectors from a wrong environment. Do take a note.

Finally you will be able to see Triggers while creating custom connectors…

Hope reviewing these will help…

Cheers,

PMDY

Opening a Custom page to capture entity details for Case Rejection in Model Driven Apps

Hi Folks,

In this blog post, I will talk about implementing a custom page for your implementations.

Here in our use case, customer want to see a pop up dialog box where they can reject the cases from a button and when reject is clicked, there should be a dialog box to capture the reject reason and comments and update them back to the record. So for this we had to implement a custom page and called from a Ribbon button. If you just want to show an alert, you can very easily implement using JavaScript with the help of OOB Alert Dialog…

Xrm.Navigation.openAlertDialog(alertStrings,alertOptions).then(closeCallback,errorCallback);

But in case as user want to update entity details like optionset field, directly from the pop up, you should consider using the approach as we did using a custom page.

.

All we have used is JavaScript, Ribbon Workbench and Custom Page…First is to design the custom page in https://make.powerapps.com/

The optionset for Reject Reason is bound to the Reject Reason combo box using the below property.

On the App start, we will set the parameter with what we have supplied from the ribbon on-click function.

On the OnSelect property of the Save button, we can use the below function

Function:

If(IsBlank(RejectReasondrp.Selected) Or IsBlank(txtRemarks.Value),Set(varmsg,"Fill both the values")&&Set(varmsgpopup, true),
Patch(Cases,LookUp(Cases,Case=GUID(CaseId.Text)),{Comments:txtRemarks.Value,'Rejection Reason':RejectReasondrp.Selected.Value}));
If(!IsBlank(RejectReasondrp.Selected) && !IsBlank(txtRemarks.Value),Set(varShowpopup,true),"");
view raw OnSavePowerFx hosted with ❤ by GitHub

Here’s the js code for the button OnClick Event…

//On Click of Reject button
onClickOfRejectRibbonButton: function (executionContext) {
"use strict";
var formContext = executionContext;
var recordId = formContext.data.entity.getId();
recordId = recordId.replace("{", "");
recordId = recordId.replace("}", "");
var contactId = formContext.getAttribute("customerid").getValue()[0].id;
contactId = contactId.replace("{", "");
contactId = contactId.replace("}", "");
var pageInput = {
pageType: "custom",
name: "new_custompage_7e429",
entityName: "incident",
recordId: recordId
};
var navigationOptions = {
target: 2,
position: 1,
height: 400,
width: 700,
title: "Case Resolution Confirmation" // Enter Title Of Your Choice
};
//Using navigateTo Client API.
Xrm.Navigation.navigateTo(pageInput, navigationOptions).then(
function success() {
// Run code on success
//formContext.data.refresh();
},
function error() {
// Handle errors
formContext.data.refresh();
}
);
}

Here the ribbon workbench customization added…

Finally publish the customizations and add the custom page to the model driven app…don’t forget to add this to your app as this mandatory to get the authorization to your page as below, else you see below error in developer tools of your browser as below…and no custom page opens up…

That’s it…when a Reject is clicked, you should a see a page as below..

Upon entering the details as above, you will be shown a confirmation screen as below..

Once you click on Close, the selected details will be updated back in the record.

Hope this helps someone implementing custom page for a similar requirement….

Cheers,

PMDY

The refresh token has expired due to inactivity when connecting to Power Pages using Power Apps CLI – Quick Fix

Hi Folks,

This post is about a quick fix for an error occurred with Power Apps CLI.

I was trying to connect to my organization using CLI and that’s when I encountered this error.

Prerequisites:

Power Apps CLI, Visual Studio Code

After installing the prerequisites, I was trying to connect to my Power Pages available in my organization from VS Code terminal using below command.

pac paportalist 

It’s then I encountered the below error

It’s then I understood that due to inactivity, it is failing…

Your Power Platform CLI connection is failing due to an expired refresh token and an ExternalTokenManagement Authentication configuration issue. Here’s how you can resolve it:

Fix:

Reauthenticate with Dataverse

pac auth clear
pac auth create --url https://orgXXX.crm8.dynamics.com --username admin@Ecellors.onmicrosoft.com --password [your password]

Creating new authentication profile resolves this issue…

    Now try to run the above command.

    This should prompt a new login window to authenticate your request, provide the details and you should be able to login.

    Hope this helps..

    Cheers,

    PMDY

    Deploy dependent assemblies easily using PAC CLI

    Hi Folks,

    This is another post related to Plugins in Dynamics 365 CE.

    Considering medium to large scale implementations, there isn’t a single Power Platform Project which don’t require merging of external assemblies.

    We relied on ILMerge to merge those assemblies into a single DLL. We used to search for ILMerge assemblies in Nuget and installed them for use.

    Then the plugins are signed in for several reasons, primarily related to security, assembly integrity, and versioning of the sandbox worker process.

    But either of the above are no longer needed with the help of Dependent Assembly feature…with few simple steps, you can build the Plugin…Interesting, isn’t it, read on…

    Pre requisites:

    • Download Visual Studio 2022 Community Edition here
    • Download VS Code from here
    • Download Plugin registration tool from here
    • Download PAC CLI from here
    • Download and install NuGet Package Explorer from this link NuGet Package Explorer open the NuGet Package Explorer

    Avoid Direct Plugin Project Creation in Visual Studio

    • Never create a Plugin project directly from Visual Studio or any other IDE here after.
    Use Microsoft PowerApps CLI instead
    • Always use Power Apps CLI as it easy and only requires a single command to create the entire Plugin project scaffolding
    • This ensures a standardized and reliable development environment.
    • It automatically creates a Nuget Package file that will be used to avoid ‘Could not load assemblies or its dependencies‘.

    Ok, let’s begin.

    Once you have downloaded all the prerequisites mentioned, make sure you have installed them in your local machine. Others are straight forward to download, for NuGet Package explorer, you need to search in Windows store to install.

    1. Create a local folder for the Plugins

    Navigate to that folder from VS Code

    Now open terminal, run the pac command as below

    Execute the following command to create plugin project 

    • Browse to the directory where you want to create the plugin project
    • Execute the command on CMD to create plugin project “pac plugin init

    A plugin project will be created at your desired location as follows

    Plugin project in local folder will be created as below

    That’s it, you can close the VS Code for now.

    Click on the CS Proj file and open it in Visual Studio

    By default, 2 files are automatically created when you create a plugin project as shown above.

    Now will install Bouncy Castle which is an external library, right click on the Plugin Solution –> Manage Nuge Packages

    I have added Bouncy Castle NuGet Package to my plugin project for Encryption and Decryption. You can have your own required NuGet Package as per your need.

    Build your project

    After a successful build, you will get the output result as follows

    Browse the directory of your project

    Open the file Plugin_Project.1.0.0.nupkg in Nuget Package Explorer by double clicking it

    Now you can see that this nuget package file contains the information related to the added nuget package of Bouncy Castle that we want to include in our plugin project package as follows. In your case, you can have the required nuget package that you want to add 

    Now open up plugin registration tool

    Click to create new connection

    Provide login details and login

    Click to Register New Package

    Browse to the directory where your nuget package file was created automatically when you build the project and import this file 

    Select the Command Data Service Default Solution and import it

    Click on view and Display by package

    Now your Plugin Project is successfully registered with all dependent assemblies and ready to use.

    While this post gives you a structure on how you can do build a plugin assembly, you can add the business logic as per your need.

    Conclusion:

    In conclusion, navigating the intricacies of Microsoft Dynamics 365 CRM plugins demands a nuanced approach, especially when dealing with NuGet Packages and dependent assemblies. This article has delved into the critical process of resolving the persistent ‘Could not load assemblies or its dependencies‘ issue, offering a comprehensive, step-by-step demonstration.

    By following the recommended best practices, such as avoiding direct plugin project creation in Visual Studio and harnessing the power of Microsoft PowerApps CLI, developers can establish a standardized and reliable development environment. The CLI’s automatic creation of a NuGet Package file not only streamlines the process but also reduces the errors.

    To further facilitate your journey, prerequisites such as downloading and installing essential tools like the Plugin Registration tool, Microsoft PowerApps CLI, and NuGet Package Explorer are highlighted. The guide emphasizes the significance of these tools in ensuring a smooth plugin development experience.

    By adopting these practices and incorporating the suggested steps into your workflow, you not only troubleshoot existing issues but also fortify your understanding of the entire process. Take charge of your Dynamics 365 CRM plugin development, elevate your skills, and sidestep common pitfalls by mastering the art of handling NuGet Packages and dependencies seamlessly.

    References:

    Build and package plug-in code

    Cheers,

    PMDY 

    Fix Plugin Registration Tool Connection Issues with Multi-Factor Authentication (MFA) Enabled in Power Platform

    Hi Folks,

    It’s been a since I posted on Power Platform Plugins, so this blog post talks about one small tip when connecting to your Power Platform Environment from Plugin Registration Tool either if you were connecting from Standalone Plugin Registration Tool or using Plugin Registration Tool from XrmToolBox.

    If you were looking to install plugin registration tool itself, you can check the below post or if you want to learn about all Plugin related issues at once, you can check the references at the bottom of this post, else you can continue reading this post.

    If you don’t know this tip, it will be difficult and least you will spend many minutes figuring out the error message you see in the Plugin registration tool.

    This is applicable for applications who have MFA enabled, even if you haven’t enabled, it was enabled by Microsoft by default to enforce security.

    As usually, you select:

    1. Office 365
    2. Enable Display list of available organizations, Show Advanced
    3. Provide User Name, Password
    4. Click on Login

    You will be prompted this error in such case

    ======================================================================================================================
    Source : Microsoft.IdentityModel.Clients.ActiveDirectory
    Method : MoveNext
    Date : 12/4/2025
    Time : 5:09:52 pm
    Error : AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use multi-factor authentication to access '00000007-0000-0000-c000-000000000000'. Trace ID: 7a7cac23-056c-4e77-ba82-98d50c0b7001 Correlation ID: d8b32fe6-6197-4d9a-a460-3834c8dc292a Timestamp: 2025-04-12 09:09:52Z
    Stack Trace : at Microsoft.Xrm.Tooling.Connector.CrmWebSvc.ProcessAdalExecption(Uri serviceUrl, ClientCredentials clientCredentials, X509Certificate2 userCert, UserIdentifier& user, String clientId, Uri redirectUri, PromptBehavior promptBehavior, String tokenCachePath, Boolean isOnPrem, String authority, Uri& targetServiceUrl, AuthenticationContext& authContext, String& resource, CrmLogEntry logSink, Boolean useDefaultCreds, String& authToken, AdalException adalEx)
    at Microsoft.Xrm.Tooling.Connector.CrmWebSvc.ExecuteAuthenticateServiceProcess(Uri serviceUrl, ClientCredentials clientCredentials, X509Certificate2 userCert, UserIdentifier user, String clientId, Uri redirectUri, PromptBehavior promptBehavior, String tokenCachePath, Boolean isOnPrem, String authority, Uri& targetServiceUrl, AuthenticationContext& authContext, String& resource, UserIdentifier& userIdent, CrmLogEntry logSink, Boolean useDefaultCreds, SecureString clientSecret)
    at Microsoft.Xrm.Tooling.Connector.CrmWebSvc.DiscoverGlobalOrganizations(Uri discoveryServiceUri, ClientCredentials clientCredentials, X509Certificate2 loginCertificate, UserIdentifier user, String clientId, Uri redirectUri, PromptBehavior promptBehavior, String tokenCachePath, Boolean isOnPrem, String authority, UserIdentifier& userOut, CrmLogEntry logSink, Boolean useGlobalDisco, Boolean useDefaultCreds)
    at Microsoft.Xrm.Tooling.Connector.CrmWebSvc.DiscoverOrganizations(Uri discoveryServiceUri, ClientCredentials clientCredentials, UserIdentifier user, String clientId, Uri redirectUri, PromptBehavior promptBehavior, String tokenCachePath, Boolean isOnPrem, String authority, UserIdentifier& userOut, CrmLogEntry logSink, Boolean useGlobalDisco, Boolean useDefaultCreds)
    at Microsoft.Xrm.Tooling.CrmConnectControl.CrmConnectionManager.QueryOAuthDiscoveryServer(Uri discoServer, ClientCredentials liveCreds, UserIdentifier user, String clientId, Uri redirectUri, PromptBehavior promptBehavior, String tokenCachePath, Boolean useGlobalDisco)
    at Microsoft.Xrm.Tooling.CrmConnectControl.CrmConnectionManager.QueryOnlineServerList(ObservableCollection`1 svrs, OrganizationDetailCollection col, ClientCredentials liveCreds, Uri trimToDiscoveryUri, Uri globalDiscoUriToUse)
    at Microsoft.Xrm.Tooling.CrmConnectControl.CrmConnectionManager.FindCrmOnlineDiscoveryServer(ClientCredentials liveCreds)
    at Microsoft.Xrm.Tooling.CrmConnectControl.CrmConnectionManager.ValidateServerConnection(CrmOrgByServer selectedOrg)
    ======================================================================================================================
    Inner Exception Level 1 :
    Source : Not Provided
    Method : Not Provided
    Date : 12/4/2025
    Time : 5:09:52 pm
    Error : Response status code does not indicate success: 400 (BadRequest).
    Stack Trace : Not Provided
    ======================================================================================================================
    Inner Exception Level 2 :
    Source : Not Provided
    Method : Not Provided
    Date : 12/4/2025
    Time : 5:09:52 pm
    Error : {"error":"interaction_required","error_description":"AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use multi-factor authentication to access '00000007-0000-0000-c000-000000000000'. Trace ID: 7a7cac23-056c-4e77-ba82-98d50c0b7001 Correlation ID: d8b32fe6-6197-4d9a-a460-3834c8dc292a Timestamp: 2025-04-12 09:09:52Z","error_codes":[50076],"timestamp":"2025-04-12 09:09:52Z","trace_id":"7a7cac23-056c-4e77-ba82-98d50c0b7001","correlation_id":"d8b32fe6-6197-4d9a-a460-3834c8dc292a","error_uri":"https://login.microsoftonline.com/error?code=50076","suberror":"basic_action"}: Unknown error
    Stack Trace : Not Provided
    ======================================================================================================================
    ======================================================================================================================
    Inner Exception Level 2 :
    Source : Not Provided
    Method : Not Provided
    Date : 12/4/2025
    Time : 5:09:52 pm
    Error : {"error":"interaction_required","error_description":"AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use multi-factor authentication to access '00000007-0000-0000-c000-000000000000'. Trace ID: 7a7cac23-056c-4e77-ba82-98d50c0b7001 Correlation ID: d8b32fe6-6197-4d9a-a460-3834c8dc292a Timestamp: 2025-04-12 09:09:52Z","error_codes":[50076],"timestamp":"2025-04-12 09:09:52Z","trace_id":"7a7cac23-056c-4e77-ba82-98d50c0b7001","correlation_id":"d8b32fe6-6197-4d9a-a460-3834c8dc292a","error_uri":"https://login.microsoftonline.com/error?code=50076","suberror":"basic_action"}: Unknown error
    Stack Trace : Not Provided
    ======================================================================================================================

    Based on the above inner exception, we can clearly understand that it is looking for Multifactor Authentication, so untick the Show Advanced checkbox, it then asks for Multifactor Authentication as shown below.

    That’s it, with this simple tick of unchecking the Show Advanced, you were able to overcome this error, how cool is it…?

    I have written lot of articles with respect to Plugin registration tool, you can check them below

    Issues related to Plugins and Plugin Registration Tool

    Hope this helps…

    Cheers,

    PMDY

    Creating In-App Notifications in Model Driven Apps in an easier way – Quick Review

    Hi Folks,

    In App notifications are trending these days where many customers are showing interest in implementing these for their businesses.

    So, in this blog post, I am going to show you the easiest way to generate In App notification using XrmToolBox in few clicks. Use the below tool to generate one.

    So, let me walk you through step by step

    Step 1: Open In App Notification Builder in XrmToolBox

    Step 2: In App notification is a setting that should be enabled at App level, so meaning if you have developed few Model Driven Apps, you will be able to enable the In App notification individually for each one of them.

    Step 3: In the above snapshot, we should be able to select the respective App for which we want to enable the In App Notification. Red bubble besides indicate that the In App notification is not enabled for this App.

    So, we need to enable it by clicking on the red icon itself, you should then be able to get this prompt as below.

    Step 5: Upon confirming the confirmation dialog box, the In App notification will be enabled for that App and you the red button turns to green as below saying that In App Notification is enabled.

    Now that the In App notification is enabled in the App, we will proceed with the remaining setup.

    Step 6: You can proceed to give a meaningful title, body for you In App Notification. Also mention the required toast type and specify the expiry duration, Icon. Also Click on Add icon and choose the action required to be performed when In App notification is clicked.

    Step 9: You can even choose the type of action to be performed…

    For example, let’s use to open as dialog and show list view

    Your screen should look something like below

    Step 10: Once done, you can click on create and that’s it you have now created In App Notification. Now let’s test this for the user who have priveleges to access this App.

    If not, you will face this error..

    Log in with user account for which the In App Notification is triggered.

    Hurray!!!! That’s it, how easy it was to create In App Notification in Low Code manner.

    You can even get the code behind this as well…

    However, there were other ways to trigger the In App Notification from a Pro Code angle, let’s discuss those as well.

    In this case you need to manually turn the In App Notification feature on by going to settings for the Model Driven App as below first.

    Notifications can be sent using the SendAppNotification message using SDK.

    You can either trigger from and can choose based on your convenience to trigger a similar notification.

    Client Scripting

    var systemuserid = '<user-guid>';
    var data = {
    "actions": [
    {
    "data": {
    "url": "?pagetype=entitylist&etn=account&viewid=00000000-0000-0000-00aa-000010001002",
    "navigationTarget": "dialog"
    },
    "title": "Link to list of notifications"
    }
    ]
    };
    var notificationRecord =
    {
    'title': 'Learning In App Notificaiton',
    'body': `In-App Notifications in Model-Driven Apps are messages or alerts designed to notify users of important events or actions within the app. These notifications appear directly inside the application, providing a seamless way to deliver information without relying on external methods such as emails.`,
    'ownerid@odata.bind': '/systemusers(' + systemuserid + ')',
    'icontype': 100000003, // Warning
    'toasttype': 200000000, // Timed
    'ttlinseconds': 1209600,
    'data': JSON.stringify(data)
    }
    Xrm.WebApi.createRecord('appnotification', notificationRecord).
    then(
    function success(result) {
    console.log('notification created with single action: ' + result.id);
    },
    function (error) {
    console.log(error.message);
    // handle error conditions
    }
    );
    view raw JS hosted with ❤ by GitHub

    Plugin/SDK

    var notification = new Entity("appnotification")
    {
    ["title"] = @"Learning In App Notificaiton",
    ["body"] = @"In-App Notifications in Model-Driven Apps are messages or alerts designed to notify users of important events or actions within the app. These notifications appear directly inside the application, providing a seamless way to deliver information without relying on external methods such as emails.",
    ["ownerid"] = new EntityReference("systemuser", new Guid("00000000-0000-0000-0000-000000000000")),
    ["icontype"] = new OptionSetValue(100000003), // Warning
    ["toasttype"] = new OptionSetValue(200000000), // Timed
    ["ttlinseconds"] = 1209600,
    ["data"] = @"{
    ""actions"": [
    {
    ""data"": {
    ""url"": ""?pagetype=entitylist&etn=account&viewid=00000000-0000-0000-00aa-000010001002"",
    ""navigationTarget"": ""dialog""
    },
    ""title"": ""Link to list of notifications""
    }
    ]
    }"
    };
    service.Create(notification);
    view raw gistfile1.txt hosted with ❤ by GitHub

    Power Automate:

    You should design your Power Automate something like below to trigger a similar notification.

    Note: Currently In App Notification will be triggered for only Model Driven Apps.

    Reference:

    In App Notification Documentation

    Hope this saves some of your time…

    Cheers,

    PMDY

    Microsoft Power Platform Center of Excellence (CoE) Starter Kit – Core Components – Setup wizard – Learn COE #02

    Hi Folks,

    This post is continuation to my previous post on COE Starter Kit, if in case you have just landed on this page. I would suggest go here and check out my blog post on introduction to COE Starter Kit.

    Important:

    Do test out each and every component, rolling out to production without testing as you need to keep in mind that there were many flows which can trigger emails to users which may keep them annoyed.

    You need to install the components present in the COE Starter Kit extracted folder in the dedicated environment, preferably Sandbox environment (not in Default environment, so that you can test it out first before moving changes to Production), make sure you have Dataverse installed in the environment. First let’s install the Solutions and later we can proceed to customize them.

    Install CenterofExcellenceCoreComponents managed solution from your extracted folder, the exact version may be different and differ as the time goes at the time of installing this, the version was as below CenterofExcellenceCoreComponents_4.24_managed

    Then proceed to click on Import as we will be configuring these environment variables whenever required later. It takes a couple of seconds to process, it asks to set the connections which I had talked about in previous post, just create new connection if one not available and click next. Make sure you have green checkboxes for each connection, and you are good to click next.

    Then you will be presented with the screen to input Environment variables as below, we will configure later so for now, just proceed by clicking on Import button.

    The import process may take a while like around 15 minutes, once imported, you should see a notification message on your screen something like below.

    Step 1:

    You will have a bunch of Apps, Flows installed in your environment. Configure the COE Settings by opening the Centre of Excellence setup and upgrade wizard from the installed Center of Excellence – Core Components managed solution.

    It should look something like below when opened. You will be presented with some prerequisites

    Proceed with this step-by-step configuration, you don’t need to change any of the setting, just proceed by clicking on Next.

    Step 2: In this step, you can configure different communication groups to coordinate by creating different personas

    You can click on Configure group, choose the group from the drop down and enter the details and click create a group.

    Provide a group name and email address without domain in the next steps and proceed to create a group, these were actually Microsoft 365 groups.

    Once you have setup, it should show..

    However, this step is optional, but for efficient tracking and maximum benefit of COE, it is recommended to set this up.

    Step 3: While the tenant Id gets populated automatically. Make sure to select no here instead of yes if you were using Sandbox or Production Environment and configure your Admin email and click Next.

    Step 4: Configure the inventory data source.

    Tip: In case you were not able to see the entire content in the page, you can minimize the Copilot and press F11 so that entire text in the page would be visible to you.

    This is required for the Power Platform Admin Connectors to crawl your tenant data and store them in Dataverse tables. This is similar to how search engines crawl entire internet to show any search results. While Data export is in preview, so we proceed with using Cloud flows.

    Click Next.

    Step 5:

    This step is Run the setup flows, click on refresh to start the process. In the background, all the necessary admin flows will be running. Refresh again after 15 minutes to see all the 3 admin flows are running and collecting your tenant data as below and click Next.

    Step 6:

    In the next step, make sure you set all the inventory flows to On.

    By the way inventory flows are a set of flows that are repeatedly gathering a lot of information about your Power Platform tenant. This includes all Canvas Apps, Model Driven Apps, Power Pages, Cloud Flows, Desktop Flows, Power Virtual Agent Bots, Connectors, Solutions and even more.

    To enable them, open the COE Admin Command Center App from Center of Excellence – Core Components Solution. Make sure you turn on all the flows available.

    So, after turning on all the flows, come back and check on Center of Excellence Wizard Setup, you should see a message something like below saying all flows have been turned on.

    Configure data flows is optional, as we haven’t configured it earlier, this step would be skipped.

    Step 7: In the next step, all the Apps came in with Power Platform COE Kit should be shared accordingly based on your actual requirement to different. personas.

    Step 8:

    This part of the wizard currently consists of a collection of links to resources, helping to configure and use the Power BI Dashboards included in the CoE.

    Finish

    Once you click Done, you will be presented with more features to setup.

    These setups have similar structure but varies a bit based on the feature architecture.

    As we got started with setting Starter Kit and had set up the Core Components of the Starter Kit which is important one, now you can keep customizing further, in the future posts, we will see how we can set up Center of Excellence – Governance Components, Center of Excellence – Innovation Backlog. These components are required to finally set up the Power BI Dashboard and use effectively to plan your strategy.

    Everyone who’s ever installed or updated the CoE knows how time-consuming it can be. Not just the setup procedure, but also the learning process, the evaluation and finally the configuration and adoption of new features. It’s definitely challenging to keep up with all this. Especially since new features are delivered almost every month. This attempt from me is to try my best to keep it concise, yet making you understand the process.

    While such setup wizard is clear and handy resource to get an overview of the CoE architecture and a great starting point for finding any documentation. This simplifies administration, operations, maintenance and may be even customizations.

    If you face issues using the COE Starter Kit, you can always report them at https://aka.ms/coe-starter-kit-issues

    Hope this helps…. someone setting up COE starter kit…. if you have any feedback or questions, do let me know in comments….

    Cheers,

    PMDY