DevOps pipeline for Azure functions

This article talks about building and creating pipelines on Azure DevOps for Azure functions .NET core/.NET 6

The steps to build a build and release pipelines are follows:

  1. Select your Repo
  2. Configure a pipeline template ex. ASP.NET, ASP.NET core, Starter
  3. Under a starter pipeline – There are 3 steps to create a starter pipeline.
    1. Build a script for compiling and building the code
    2. A script to archive code files in a zip folder
    3. Publish the artifact

The first step is to create a build pipeline.

In Azure DevOps -> create a new pipeline -> Select Azure Repos Git -> Select the Repository -> Select a starter pipeline

In Review your pipeline step, remove the default steps from the script. We will use the assistant to build the scripts. From the assistant on the right side, select .NET core task and add the command, path to project, and arguments, and click on the Add button

The Arguments are: –output $(Build.BinariesDirectory)/publish_output –configuration Release

You can also make a variable for the argument value and use the variable.

Let’s add the code to archive this project into a zip file.

Select Archive files from the Task assistant. Archive the files under publish_output folder and uncheck the prepend option

This is going to create an archive under the staging directory.

Let’s go ahead and publish this artifact. Select “publish build artifacts” from the Task assistant

Click “Save and Run”

You can see the published artifact in the build job
The published folder will look this:

Power automate flow – inputs.parameters of workflow not valid

In power automate, if you run into the following error:

The ‘inputs.parameters’ of workflow operation ‘Get_a_row_by_ID_3’ of type ‘OpenApiConnection’ is not valid. Error details: The resolved string values for the following parameters are invalid, they may not be null or empty: ‘recordId’

Check your previous steps, and make sure the parameter that you’re passing into your step (in this case, Get Row by ID) Row Id gets a valid record id (guid). In the above flow, in Get row by ID 2, I was retrieving a record and selecting only one column in Select columns, this attribute is a lookup on the entity record. This wasn’t bringing the result in the desired result in the body upon running the flow, and I was referencing this value in the Get row by Id 3 step, hence the error, I am referring to a value which doesn’t exist.

The way to reference the column in the select column is _new_accountid_value

After I added the above column, the flow ran successfully, and the value was available in the next steps.

Close Canvas App window using PCF button

Canvas Apps can be launched from within the Dynamics CE using a ribbon button and calling a javascript funtion to open the Canvas App in a new window using

However, once a Canvas app window is launched, you can’t close the window. Microsoft provides Exit() and Exit(true) functions. Exit() navigates away from the current page and redirects to the list of canvas apps, while Exit(true) signs out the user and navigates to the login page. In either case, the window should be closed manually by the user.

I found a way to close this window using PCF button embedded within a canvas app. This a two step process:

  1. Creating and deploying PCF button control to the Dynamics CE/CDS/Dataverse environment
  2. Adding this PCF button control to the Canvas App
  1. Creating and deploying the PCF button control to the Dynamics CE environment:

You can follow this blog to create and deploy the PCF button control with one additional changes. In the submitClicked(event:Event) handler, add the following code

2. Adding the PCF button control to the Canvas App

To enable PCF control to be used within the Canvas App, you need to:

  • Enable power apps component framework for canvas app in the power platform admin center
  • Enable Components in Preview Features of the Canvas App settings

Enable power apps component framework for canvas app in the power platform admin center

  • Go to
  • Select the Environment where you want to embed the PCF control
  • Click Settings -> Product -> Features
  • Enable the Power Apps component framework for canvas apps

The next step is to Enable Components in Preview Features of the Canvas App settings

  1. Open the canvas app
  2. Select File -> Settings -> Advance Settings
  3. Under Preview Features -> Enable Components

Now that the PCF control components is enabled for your CDS/Dataverse environment and the Canvas App, let’s embed this control in your Canvas App.

  • Go to the canvas App
  • Select the Insert tab -> Custom -> Import component
  • You will notice two tabs, Canvas and Code. Select the “Code” tab
  • Select your PCF control (this is visible only if your pcf control is deployed to this CDS environment, see step 1 – creating and deploying the pcf control) from the list, and click on Import
  • Importing this component will enable the Code components section in your Insert tab in the left navigation and display your PCF control
  • Drag this control across to your Canvas App
  • Save and Publish

Test this out by opening the canvas app from the ribbon button. Now, clicking on this button should close the Canvas App.

Create a new PCF Button Control

  1. Create a new folder in your directory

2. Open Visual Studio Developer 2019 command prompt and navigate to the NewPcfButton folder, and type the following pcf command:
pac pcf init –namespace CanvasAppClosePcfControl –name CanvasAppClose –template field

You should see a pcf project getting created in the NewPcfButton folder.

3. Open Visual studio code, and open this project by navigating to the NewPcfButton folder

4. Now, we will need to install the project dependencies. Click on Terminal in the visual studio code ribbon and select New Terminal. Type the command in the terminal – npm install

You’ll notice a new folder “node_modules” created in the NewPcfButton folder
5. Next, type npm run build to build the solution

6. Type npm start to watch the pcf control in your local browser. You can debug and test your pcf control here

Now that we have the pcf project created, built, and run successfully, let’s go ahead and customize and add a new PCF button control. In this post, we will have not have either a bound/unbound control. Therefore, in your ControlManifest.Input.xml file, command out the following line:

<!–<property name=”sampleProperty” display-name-key=”Property_Display_Key” description-key=”Property_Desc_Key” of-type=”SingleLine.Text” usage=”bound” required=”true” />–>

Next, In your index.ts file, define the following global variables and an eventSubmitClicked event

private _context:ComponentFramework.Context<IInputs>;
private theNotifyOutputChanged:() => void;
private _container:HTMLDivElement;
//Html Elements - Creating a text box and a button

private _eleMainContainer:HTMLDivElement;
private _eleButton:HTMLButtonElement;
private eventSubmitClicked:EventListenerOrEventListenerObject;

Next, inside the init function, write the following code:

this._container = container;
this._context = context;
this.theNotifyOutputChanged = notifyOutputChanged;
//The assignment of the event listener to the function should be done before creating the UI        

this.eventSubmitClicked = this.submitClicked.bind(this);
//Create UI        

//Main Container
this._eleMainContainer = document.createElement("div");
this._eleMainContainer.className = "mydiv";
//Define a button
this._eleButton = document.createElement("button");
this._eleButton.className = "canvasAppButton";             
this._eleButton.innerHTML = "Finish";
this._eleButton.addEventListener("click", this.eventSubmitClicked);
//Add the button inside the main container, and the main container inside the container


Let’s give this button some css styling. Notice, I have a css class “canvasAppButton” attached to this button. The idea here is to apply css to the button control, the same css styling as that of the Canvas App buttons. Create a new subfolder “css” under the main project folder and add the canvas.css file.

Inside the css file, apply the css properties to the class

    border-radius: 8px;
    font-family: “Open Sans”, sans-serif;
    font-weight: 600;
    font-size: 16pt;

Reference this css file under the ControlManifest.Input.xml file in the <resources> section.

Now, that the button is created, we bind the button to the submitClicked event. Write the following function below your init function.

//Custom event handler – for the button
 private submitClicked(event: Event): void{  alert(“Button is clicked”);    }

Next, build the project using npm run build, and npm start to see the button in action

Click on the button.

The pcf button control works!!


Let’s work on deploying this pcf control to CRM

The first step is to create a solution folder inside the NewPcfControl project folder

The next step is to create a publisher and publisher prefix. This will bind the control to the given publisher and the publisher prefix. When this is imported into CRM, a new publisher and the publisher prefix is created with the given names and the pcf control is bound to that prefix. You could also make use of your existing publisher and publisher prefix if you don’t want to create a new one. Type the following command in the Developer Command prompt for VS 2019

pac solution init –publisher-name MyCompany –publisher-prefix new

The next step is add the pcf control project solution reference to the solution folder. Type the following command, but make sure you replace the path with your project path

pac solution add-reference –path “C:\Users\HameedHussain\Downloads\NewPcfButton”

Next, build the solution directory, type the following command:

msbuild /t:build /restore

This command will build the CRM zip file, that you will use to import your solution into CRM. Let’s look at the Solution and see where we would find the solution zip file

The CRM zip file is found inside the bin folder

Import the file into CRM, and use the PCF control as you see fit in any entity.

Additional Notes:

By default, the solution imported will have the display name and Name of the solution as “Solution”. The default solution version is 1.0 This is because the solution.xml contains the unique name, and description of the CRM solution as “Solution”. You can change the Unique name and Name of the solution as per your solution naming convention. See below.

If you make changes to the Pcf control code and wish to import the new changes, just run the build command (npm run build) and make directory (msbuild /t:build /restore), and import the solution. It’s a good practice to update the solution version on every build.

‘The ‘version’ attribute is invalid – The value ‘1.0’ is invalid according to its datatype ‘versionType’ – The Pattern constraint failed.’

While implementing the PCF control, after building the solution, if you run into the following issue while importing the custom control solution

String”>An error has occurred. Try this action again. If the problem continues, check the Microsoft Dynamics 365 Community for solutions or contact your organization’s Microsoft Dynamics 365 Administrator. Finally, you can contact Microsoft Support. : Microsoft.Crm.Tools.ImportExportPublish.ImportCustomControlException: CustomControl with name failed to import with error: The import manifest file is invalid. XSD validation failed with the following error: ‘The import manifest file is invalid. XSD validation failed with the following error: ‘The ‘version’ attribute is invalid – The value ‘1.0’ is invalid according to its datatype ‘versionType’ – The Pattern constraint failed.’.”‘.” —> Microsoft.Crm.CrmException: The import manifest file is invalid. XSD validation failed with the following error: ‘The import manifest file is invalid. XSD validation failed with the following error: ‘The ‘version’ attribute is invalid – The value ‘1.0’ is invalid according to its datatype ‘versionType’ – The Pattern constraint failed.’.”‘.”at Microsoft.Crm.Tools.ImportExportPublish.CustomControlsInstaller.ValidateSchema()at Microsoft.Crm.Tools.ImportExportPublish.CustomControlsInstaller.Validate(ExecutionContext context)at Microsoft.Crm.Tools.ImportExportPublish.CustomControlsInstaller.Install() — End of inner exception stack trace — at Microsoft.Crm.Tools.ImportExportPublish.CustomControlsInstaller.Install()at Microsoft.Crm.Tools.ImportExportPublish.ImportCustomControlsHandler.ImportItem()

It is most likely due the version attribute being invalid. Make sure the version is 1.0.0 in your ControlManifest.Input.xml file

Power Automate Flow – Flow client error returned with status code “Bad Request”

In Power Automate Flow, you may encounter the error below when tryin to save the flow

Request to XRM API failed with error: ‘Message: Flow client error returned with status code “BadRequest” and details “{“error”:{“code”:”InvalidOpenApiFlow”,”message”:”Flow save failed with code ‘InvalidTemplate’ and message ‘The template validation failed: ‘The repetition action(s) ‘Apply_to_each’ referenced by ‘inputs’ in action ‘Create_a_new_record’ are not defined in the template.’.’.”}}”. Code: 0x80060467 InnerError: Type: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]

There issue may happen when you’re trying to copy a value (example, lookup) from one flow to the other because the flow may have different collection (list of records for example) names. Therefore, when you’re copying one value from one flow to the other, you’re also copying the collection name.

For example, in one flow, your collection name is


In the other flow, if the collection name is different, and you’re copying the above value and pasting in the flow, you’ll see the “Bad Request” error.

To fix the issue, I deleted the value, selected the lookup field from the existing flow using dynamic content. It let me save the flow. This is a simple issue, often that people may figure it out, but I wanted to put it out there if someone run into this issue.

Azure DevOps Pipeline for CRM – Solution Packager

The first step in implementing the Azure DevOps pipeline process for Dynamics 365 is to extract/decompose the CRM solution into its individual components. This is done through the solution packager provided by Microsoft. You can download and install the solution packager from this link

After you install the the solution packager on your disk, you will see the following list

You can find the SolutionPackager.exe file in the CoreTools

Open windows powershell command prompt and navigate to the SolutionPackager.exe folder – D:\NuGetTools\Tools\CoreTools

Before we go to the next step, in the CRM instance, create a new empty solution and export the solution, this solution file is a zip file containing the customizations and solutions xml

We will try to extract this solution using the solution packager and see what it looks like. Go back to the powershell command, and type the following

.\SolutionPackager.exe /action:Extract /zipfile:”SolutionfolderPath/” /folder “OutputFolder”

Below, I specified where my solution is and the output folder where I want the extract the zip folder contents.

.\SolutionPackager.exe /action:Extract /zipfile:”D:\Other\DevOps\” /folder “D:\Other\DevOps\devopsfiles”

Let’s see what the output folder looks like:

Because, our solution was empty, we did not find the Enities, Plugins, Webresources folders. Let’s add few components to our Dynamics CRM solution

Export this solution, and run the SolutionPackager.exe from the powershell again, you’ll notice extraction of the different components

After you navigate to the output folder, you’ll see the different folders

Navigating inside the Entities folder, you’ll notice that the entities are split into their own folders and files containing the forms, views, charts etc.

Now, you can upload the root folder to the Git/GitHub/TFS, or any other repo, and take the next step in the integration of Azure Dev Ops pipeline for CRM.

Retain Overridecreatedon and createdby in Dynamics 365 during data import

In Dynamics 365 data import, the data imported will create records with today’s date and the data created will be logged against the user who is currently logged in even though the original createdon and createdby user could be different.

In many cases, when you’re importing an existing or legacy data in your Dynamics 365, you want to retain the original createdon date and the user who created that record. If you want to import your data with the date when the data was created, you can use overridecreatedon to override the data with the createdon date. You can also create this record against the original createdby user through impersonation. There are few ways to achieve this in Dynamics 365. You can use the kingswaysoft SSIS package to achieve this. However, in this blog, you will see how overridecreatedon and created by can achieved through xRM solution.

We have to use the OrganizationServiceProxy class to impersonate the createdby user. The class object has a property called “CallerId” that will be used to impersonate a user.

Here’s the code:

using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using System;
using System.Net;
using System.ServiceModel.Description;
using Microsoft.Xrm.Sdk.Query;namespace DynamicsProxy
  class Program
     static void Main(string[] args)
         string crmUserName = "";
         string crmPassword = "xxxxxx";
         string crmOrgHost = "";            
          ClientCredentials clientCredentials = new ClientCredentials();
          clientCredentials.UserName.UserName = crmUserName; 
            clientCredentials.UserName.Password = crmPassword; 
            // For Dynamics 365 Customer Engagement V9.X, set Security Protocol as TLS12
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            string crmApiPath = "XRMServices/2011/Organization.svc";

            Uri crmUri = new Uri(crmOrgHost + crmApiPath);

            OrganizationServiceProxy orServiceProxy = new OrganizationServiceProxy(crmUri,null,clientCredentials,null);
            //Caller Id: this is the guid of the user we want to impersonate - 4b591077-9fb8-e911-a86e-000d3a372124
            orServiceProxy.CallerId = new Guid("47d57787-433b-eb11-a813-000d3a31c841");
            Entity ent = new Entity("contact");
            ent["lastname"] = "Hameed";
            ent["overriddencreatedon"] = new DateTime(2021, 1, 19);
        catch (Exception ex)
            Console.WriteLine("Exception: "+ex.Message);

During the code execution, you may run into an error:

{“Principal user (Id=xxxx-xxx-xxx-xxx-000d3a31c841, type=8, roleCount=5, privilegeCount=811, accessMode=0), is missing prvOverrideCreatedOnCreatedBy privilege (Id=d48cf22f-f8c2-xxxx-89eb-49f8281dxxxx)

To resolve this issue, you need to enable the override createdon privilege on the security role that the user is currently assigned to

Power Automate – Invalid type. Expected Object but got Array

In Power automate, in the parse json, if the response doesn’t align with the schema of the parse json, you’ll notice different errors, one of them being “Invalid type. Expected Object but got Array”.

The Parse json schema was expecting an object as a response.

But, instead, received an array of objects, which results in the following error

This error happens when you’re passing a list of array oject records from the child workflow or list records from the previous steps.

So the parse json was expecting an object in the format of





But instead receiving an array of objects:







The output value outputs(‘Get_List_record_of_Person_Engagement_Event’)?[‘body/value’] returns an array/list of objects

To solve this problem, you need to return just the first object value from the result. Use the following expression (in the above Response body value) to return the first value from the array

first(outputs(‘Get_List_record_of_Person_Engagement_Event’)? [‘body/value’])

This will return the following object





Which is now in-line with the format that we were expecting in the parse json