ALM Common Data Service DevOps Dynamics 365 Power Platform Visual Studio

Power Platform DevOps : Part 4 – Day-to-Day ALM for Developers

Part 4 of a series of Articles co-authored by Dylan Haskins and Eugene Van Staden covering our thoughts, strategies and tools for Application Lifecycle Management (ALM) and DevOps for the Power Platform and PowerApps Portals.

Welcome to Part 4 of a series of Articles co-authored by Dylan Haskins and Eugene Van Staden covering our thoughts, strategies and tools for ALM and DevOps for the Power Platform and PowerApps Portals.

In Part 3 : Day-to-Day ALM for Consultants we covered the process that a Consultant could use on a daily basis to take part in the DevOps and ALM strategy.

The series consists of the following parts :

In this article we will showcase a possible approach and tool-set that a Developer could use to take part in our ALM process and ensure their work is committed to source control and automatically and continuously deployed.

Note: No tool-set is foolproof so you should always ensure a robust communication plan is used between all the members of your delivery team

We will cover the following day-to-day activities that a Developer might perform :

  • Open the source controlled Project created in Part 2 : Our ALM Framework and Provisioning Tool in Visual Studio
  • Create and Deploy a Plugin
  • Create and Deploy a WebResource
  • Export your Solution and configuration data
  • Commit your changes to source control
  • Sync your changes AND
  • Watch the automated build and deploy !!

Open the source controlled Project in Visual Studio

Continuing on from the work we did in Part 2 and Part 3 we can now take a look at how a Developer can add to our existing Power Platform Solution.

Start off by opening Visual studio and click on “Open a project or solution”

Browse to C:\Dev\Repos\PowerPlatformRepo (this is the Git repo we created in Part 2) and open PowerPlatformRepo.sln

This will open our Solution, it has a project structure that looks like this :

The first time you open a new Solution, we would recommend building the Solution.

Right click on the Solution ‘PowerPlatformRepo’ and select Build Solution

This will ensure a complete and successful build of all the projects as well as perform the initial NuGet Package restore to download an install all the dependent libraries that are used.

You can now switch the Build mode to SolutionPackager

To understand the rationale behind this Build mode switch, let’s take a high-level look at the Solutions project. We will take a deeper dive in Part 5 : Deconstructing the Framework : Solutions Project

The Solutions project contains all the Tools and Scripts that we use to make this ALM toolkit work, one of which is a PowerShell script called SolutionExport.ps1, this is the same Script that ran during the provisioning in Part 2 and similarly a manual version of the script was used in Part 3

The Solutions project has a Pre-build event that automatically runs this script every time the project is built in SolutionPackager mode, so whenever you want to Export and Unpack your Solution (and regenerate types using XrmContext and XrmDefinitelyTyped), you simply change your Build mode to SolutionPackager, remember to change it back to Debug to build your code for testing and deployment

Create and Deploy a Plugin

The Plugins project is the place where you go to create all your Plugin code. There is a sample Plugin there already which runs against the systemuser entity and sets the EmployeeeId field of the user to the first part of their email address. Feel free to use this sample as reference or to delete it from your Project.

For the purposes of this article we will do the following to illustrate Plugin development : (Note: this is a continuation of the Consultant work performed in Part 3, so that will be a pre-requisite)

  • Add a new field called Field B to our previously created entity Entity A
  • Update our Solution to get the latest changes from the Power Platform and Generate Early bound types
  • Create a Plugin on Entity A that sets Field A’s value based on the selection in Field B
  • Publish and Deploy our Plugin

To get started let’s make our way over to and open up our Power Platform DevOps Solution

Navigate to Entity A

Let’s add a new field called Field B and set it’s Type to OptionSet and add Items named Description 1 and Description 2 and click Done and then Save Entity

Add the Field to the Form and Save and Publish

Back in Visual Studio let’s right click on the Solutions project and Build it (remember to make sure that the Build mode is set to Debug)

This will run the SolutionExport.ps1 PowerShell script as mentioned earlier. As the outputs of the PowerShell script won’t appear in the Build Output window until it is all finished, we have made use of a PowerShell add-in called BurntToast to provide Windows Toast notifications letting you know what is happening.

Shortly after starting the build, you will be prompted for Credentials, these are the Credentials for your Development Power Platform / Dynamics 365 Environment (The Environment URL was specified during Provisioning in Part 2).

Building the Solutions project will do the following things :

  • Install all the Solution Management Tools we use.
  • Get Credentials for your Development Environment
  • Export any Configuration Data (The process for setting this up was covered in Part 3)
  • Generate Early Bound types using XrmContext
  • Generate TypeScript definition files for your WebResources using XrmDefinitelyTyped
  • Update your Power Platform Solution version number and Export and Unpack it

The Early Bound types that are generated are stored in the Entities shared project. Navigate to Entities and click on the Context folder and then select the “Show All Files” icon in the Solution Explorer window.

Here you will see the newly generated file for our custom entity Entity (ppdo_EntityA.cs), right click on it and select “Include in Project” (You’ll need to do this for any new entities you create that you wish to write code for)

Next we’ll go to the Plugins project and add a Folder called Entity A and a new Class called EntityAPlugin.cs

We have provided an Abstract Class in the Common shared project called BasePlugin which provides you easy access to all the Plugin context objects, you can update your Class to Implement it by changing your code to the following :

using Common;
using System;

namespace Plugins.EntityA
    public class EntiyAPlugin : BasePlugin
        protected override void Execute(LocalPluginContext localcontext)
            throw new NotImplementedException();

We will then update the code to set Field A to the text of the option we specify in Field B

using Common;
using Entities;
using Microsoft.Xrm.Sdk;
using System;

namespace Plugins.EntityA

    public class EntiyAPlugin : BasePlugin
        protected override void Execute(LocalPluginContext localcontext)
            ppdo_EntityA target = localcontext.PluginExecutionContext.GetTarget<ppdo_EntityA>();

            if (target == null)
                localcontext.Trace("Target was null or not of type 'ppdo_EntityA'.");
                throw new InvalidPluginExecutionException("Target was null or not of type 'ppdo_EntityA'.");

            target.ppdo_FieldA = target.ppdo_FieldB != null ? target.ppdo_FieldB.GetValueOrDefault().ToString() : "Field B does not have a Value";

To deploy our Plugins we use a tool called Spkl task runner from Scott Durow, the same MVP who brought us Ribbon Workbench. To get our plugin ready to deploy we just need to decorate it as follows (Note: Make sure to always generate a new Id for each Registration) :

    ppdo_EntityA.EntityLogicalName, StageEnum.PreOperation, ExecutionModeEnum.Synchronous,
    "", "Set Field A based on Field B", 1,
    , Description = "Set Field A based on Field B"
    , Id = "20AB0BA3-3F6E-4139-882A-273AC53ADC08"
    public class EntiyAPlugin : BasePlugin

and then run deploy-plugins.bat under the Spkl folder from our Solutions project.

We can then test our plugin by creating some records in our Power App.

Create and Deploy a WebResource

Next let’s add a WebResource to our form it will add a Form notification to our form based on our selection in Field B

The WebResources project uses TypeScript and TypeScript definitions generated using XrmDefinitelyType. We will go into more detail in Part 8

Let’s create a new TypeScript file under src/ts/forms in the WebResources project, called EntityA.ts

The content of the file should be as follows :

namespace Demo.ppdo_EntityA {
    var Form: Form.ppdo_entitya.Main.Information;

    export function onLoad(executionContext: Xrm.ExecutionContext<any>) {
        Form = <Form.ppdo_entitya.Main.Information>executionContext.getFormContext();
        let message = "You have selected - " + Form.getAttribute("ppdo_fieldb").getText();
        Form.ui.setFormNotification(message, "INFO", "NotificationID-1");

We can now build the WebResources project which will generate the JavaScript output file that we need for use on our Form.

We now need to tell Spkl that we have a new WebResource to be deployed, we do this by editing the spkl.json file in the Solutions project and modify the webresources section as follows :

We can then deploy our WebResource by running deploy-webresources.bat from our Solutions project

We then need to add the WebResource to our form and execute the onLoad function. Navigate to our form at, we will need to switch to the Classic designer to add the WebResource library.

Click Form Properties and add the Library and onLoad function as follows :

Save and Publish and then test the functionality by opening a record.

Export your Solution and configuration data

We now need to export our changes into Source control, as mentioned earlier all we need to do is build the Solutions project in Debug mode to do this.

Commit your changes to source control

We can then go to our Changes window under Team Explorer in Visual Studio and see all the updates

Fill in a Commit message, Commit All and then Sync your changes up to your Azure DevOps Git repo.

Watch your code Build and Deploy to your Deployment Staging environment (or don’t watch, it is a beautiful, automated process 😀)

That concludes Part 4, in Part 5 : Deconstructing the Framework : Solutions Project we will start our Deep Dive into deconstructing the Framework and look at the components that make up the Solutions project.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.