Power Automate: Loop Through the Dataverse Child Records and Analyse input/output

Let’s see how we can loop through the child records returned from the Dataverse, and analyse the input / outputs at each step.

Following is the example scenario we will cover.

On deactivation of Account record we want to loop through the related opportunities.

Following are the steps we will cover:

Create Cloud Flow on Account Deactivate

Create a automated cloud flow.

From outside solution.

or from inside solution.

Select Microsoft Dataverse connector and choose trigger

“When a row is added, modified or deleted”

Because this flow will trigger on deactivate, which is update of account.

Update Trigger properties

Set the flow properties as following:

First of all rename the step to Account or anything else meaningful, to easily identify this step.

Then we need to fill step properties

  • Change type: Modified
    • This defines the on change type on which this flow will trigger.
    • Other options are as following
  • Table name: Accounts
    • This option defines on which table we want flow to run.
    • Any table can be selected
  • Scope: Organization
    • This defines the scope of flow, for which users this flow will trigger.
    • Select organization if this flow should trigger for all users.
  • Select columns: statecode
    • Specify comma separated list of columns.
    • Flow will trigger If any of them are modified.
  • Filter rows: statecode eq 1
    • We are specifying flow to run when statecode is 1, which is inactive status for account.
    • In this you specify OData style filter to determine eligible rows.
  • Run as: Modifying user
    • Specify under which user context flow will run.

So far, it should look like following.

Retrieve child opportunities

Next add the Dataverse action to list rows as following.

Rename the step to List opportunities, to identify the step.

Update the List Opportunities step properties as following:

  • Table name: opportunities
    • Specifies which table records we want to retrieve, opportunity in this case.
  • Select columns: name
    • Specify the columns we want to retrieve, it’s good idea to retrieve only the required columns. In this case we are retrieving name column only.
  • Filter rows: _parentaccountid_value eq [Account from Dynamics content]
    • Specify OData style filter to filter rows.
    • Here we have specified to retrieve only the opportunity rows with parent account id matching to triggering account record id.

We can specify more properties as needed, but for this example leaving as it is.

Analyse value, body and body/value – item from list rows step

List rows step returns following Dynamics content.

  • value: value returns the array of records from the specified table in json format.
  • body: body will return the same array of records along with some other properties in body.
  • body/value – item: this contains a single instance of the array item which is single opportunity record in this case.
    • notice when we add this, automatically Apply to each step will be added.

Let’s analyse each of them.

Add three compose steps for each of them

Notice, when we add body/value – item, automatically Apply to each step will be added, and compose step will be nested inside with current item dynamic content.

Add one more step inside apply to each to extract the opportunity id

Set the expression as following to get the opportunityid from opportunity.

This should appear like this, so far.

Update each opportunity record

Next, for example we want to update current opportunity record, current item in the loop. We can do as following.

Add a Dataverse – Update a row step inside Apply to each.

and set the Table name and Row ID properties as following.

Output is from opportunity id compose item in Dynamics content window.

Here we are specifying:

  • Table name: opportunity
    • We want to update the opportunity record.
  • Row ID: id of the opportunity record we want to update, current item id in this case.

We can update any other property as we want to update on this record and same will be updated in Dataverse.

It should appear like this by now,

Save this flow

Analyse flow input / output

To test the flow and analyse the input / output, deactivate an Account record having few opportunities.

Account step

on clicking Show raw inputs

We can see the parameters passed to Dataverse.

On clicking on Show raw outputs.

List of opportunities step

On clicking Show raw inputs

We can see the filter is applied while retrieving the list of opportunities.

On click to download, json. it we can analyse all the returned data from Dataverse.

{
    "statusCode": 200,
    "headers": {
        "Vary": "Accept-Encoding",
        "x-ms-service-request-id": "e20b3c32-6708-414a-8e2a-533514cdf8e4,78409faa-75a8-4dbe-a535-b289b3327575",
        "Cache-Control": "no-cache",
        "Set-Cookie": "ARRAffinity=a50f3777a483fd4e96aadf1d0e2923f38abbc01c3df5d6cb731bbcf61f629039; domain=org1f7aa4d6.crm11.dynamics.com; path=/; secure; HttpOnly,ReqClientId=68e2c649-02b0-4fcc-89e8-d274f8d5c7bc; expires=Wed, 12-Aug-2071 20:39:52 GMT; path=/; secure; HttpOnly,ARRAffinity=a50f3777a483fd4e96aadf1d0e2923f38abbc01c3df5d6cb731bbcf61f629039; domain=org1f7aa4d6.crm11.dynamics.com; path=/; secure; HttpOnly",
        "Strict-Transport-Security": "max-age=31536000; includeSubDomains",
        "REQ_ID": "78409faa-75a8-4dbe-a535-b289b3327575",
        "AuthActivityId": "1c30924d-64e5-45eb-b690-a28fbdf484af",
        "x-ms-dop-hint": "4",
        "x-ms-ratelimit-time-remaining-xrm-requests": "1,198.57",
        "x-ms-ratelimit-burst-remaining-xrm-requests": "7995",
        "OData-Version": "4.0",
        "Preference-Applied": "odata.include-annotations=\"*\"",
        "X-Source": "1113514625493361791435986622061331061211582156719719922214047249116202212155240124105180,1113514625493361791435986622061331061211582156719719922214047249116202212155240124105180",
        "Public": "OPTIONS,GET,HEAD,POST",
        "Timing-Allow-Origin": "*",
        "Date": "Thu, 12 Aug 2021 20:39:53 GMT",
        "Allow": "OPTIONS,GET,HEAD,POST",
        "Content-Type": "application/json; odata.metadata=full",
        "Expires": "-1",
        "Content-Length": "1702"
    },
    "body": {
        "@odata.context": "https://org1f7aa4d6.crm11.dynamics.com/api/data/v9.1/$metadata#opportunities(name)",
        "#Microsoft.Dynamics.CRM.DeleteMultiple": {
            "title": "DeleteMultiple",
            "target": "https://org1f7aa4d6.crm11.dynamics.com/api/data/v9.1/opportunities/Microsoft.Dynamics.CRM.crmbaseentity/Microsoft.Dynamics.CRM.DeleteMultiple"
        },
        "@Microsoft.Dynamics.CRM.totalrecordcount": -1,
        "@Microsoft.Dynamics.CRM.totalrecordcountlimitexceeded": false,
        "value": [
            {
                "@odata.type": "#Microsoft.Dynamics.CRM.opportunity",
                "@odata.id": "https://org1f7aa4d6.crm11.dynamics.com/api/data/v9.1/opportunities(b052fc98-e8f0-ea11-a815-000d3a1b14a2)",
                "@odata.etag": "W/\"1774838\"",
                "@odata.editLink": "opportunities(b052fc98-e8f0-ea11-a815-000d3a1b14a2)",
                "name": "18 Airpot Coffee Makers for Northwind Traders",
                "opportunityid@odata.type": "#Guid",
                "opportunityid": "b052fc98-e8f0-ea11-a815-000d3a1b14a2"
            },
            {
                "@odata.type": "#Microsoft.Dynamics.CRM.opportunity",
                "@odata.id": "https://org1f7aa4d6.crm11.dynamics.com/api/data/v9.1/opportunities(2ec06197-31ec-ea11-a817-000d3a1b14a2)",
                "@odata.etag": "W/\"1773955\"",
                "@odata.editLink": "opportunities(2ec06197-31ec-ea11-a817-000d3a1b14a2)",
                "name": "2 Café Corto for Northwind Traders",
                "opportunityid@odata.type": "#Guid",
                "opportunityid": "2ec06197-31ec-ea11-a817-000d3a1b14a2"
            },
            {
                "@odata.type": "#Microsoft.Dynamics.CRM.opportunity",
                "@odata.id": "https://org1f7aa4d6.crm11.dynamics.com/api/data/v9.1/opportunities(3cbbd39d-d3f0-ea11-a815-000d3a33f3c3)",
                "@odata.etag": "W/\"1774047\"",
                "@odata.editLink": "opportunities(3cbbd39d-d3f0-ea11-a815-000d3a33f3c3)",
                "name": "5 Café BG-1 Pro Grinders for Northwind Traders",
                "opportunityid@odata.type": "#Guid",
                "opportunityid": "3cbbd39d-d3f0-ea11-a815-000d3a33f3c3"
            }
        ]
    }
}

Compose step – Value

Show raw inputs

Value Dynamic content contains all the returned rows.

Show raw outputs

Compose Step – Body

Show raw inputs

Body Dynamic content contains all the returned rows along with some other body properties.

Show raw outputs

Apply to each step

Show raw inputs

We can see a single opportunity record inside apply to each.

Apply to each – opportunityid

Apply to each – Update a row

Show raw inputs

We can see what parameters were passed as update request to Dataverse.

Show raw outputs

Conclusion

In this post we learned how we can loop through the list of child records. And on each step we analysed what are input/output to each step visualize what is going in and out.

Publish Ionic Web App to Firebase Hosting

Firebase hosting allows to host web apps, let’s see how can publish the Ionic app to Firebase hosting.

Following are the steps:

Generate production www web app folder from the Ionic app

Use following command in existing ionic project to generate production web app www folder.

ionic capacitor build browser --prod

This will generate a www folder, which we need to publish to the Firebase hosting.

Prepare Firebase Hosting project to publish the web app

Install Firebase CLI

Install Firebase CLI globally, if not already installed.

npm install -g firebase-tools

Login to Firebase, through Firebase CLI

Login to Firebase through firebase CLI, using following command. This will open a login screen in browser window. Login there.

firebase login

Create Firebase hosting project

Create new directory for firebase hosting project

mkdir hosting

Switch to directory

cd hosting

Initialize Firebase hosting project

Enter following to initialize firebase hosting project.

firebase init

Choose Yes, to initialize the Firebase project

Choose following hosting feature from listed options:

Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys

Next selected Use an existing project, because in my case I had an existing project.

Then select your project from the list.

Next question is

What do you want to use as your public directory? (public)

type www

Next Question

Configure as a single-page app (rewrite all urls to /index.html)? (y/N)

Choose Y

Next question

Set up automatic builds and deploys with GitHub? No

Enter, and firebase initialization will complete.

In the hosting folder one www folder will be created.

Copy www folder to Firebase hosting project

In the hosting folder one www folder will be created.

Replace this folder with the www folder generated above from Ionic production web app build .

Publish the web app

Finally, enter following command to publish the web app.

firebase deploy

Web app will be published to firebase hosting and you will be presented with the published web app url.

Congrats! We successfully published web app from ionic project to the Firebase hosting.

Conclusion

In this post we learned how to publish an Ionic web project to Firebase hosting.

First we generated the www folder from the Ionic app. Then We created and prepared a new project for publishing to Firebase hosting. In the Firebase hosting project we copied the www folder from the Ionic app and then finally published to Firebase hosting using firebase deploy

TypeScript / JavaScript: Create Array Chunks from Given Array

Often we need to process the array in batches rather than processing whole of the array at once. For that purpose we may need to split the array in chunks of a specified size.

Let’s see how we can split the array in chunks of a specified chunk size.

Consider the following array.

const given = [3, 4, 5, 2, 6, 3, 2, 25, 5, 2, 45, 7, 4, 3];

and we want to split this array into chunks of chunk_size = 3

const given = [3, 4, 5, 2, 6, 3, 2, 25, 5, 2, 45, 7, 4, 3];
const chunk_size = 3;

const chunks = Array.from({ length: Math.ceil(given.length / chunk_size) }).map(() => given.splice(0, chunk_size));

console.table(chunks);

Output

Array.from()

Array.from() method creates array of length defined by the length property.

const arr = Array.from({length:3});
console.table(arr);

Output

Array.prototype.map()

map method can be used to transform each element of the array.

It returns a new array of elements applied the specified function.

const array1 = [1, 4, 9, 16];

// pass a function to map
const map1 = array1.map(x => x * 2);

console.log(map1);
// expected output: Array [2, 8, 18, 32]

Array.prototype.splice()

splice(start, deleteCount)

splice method can remove the number of elements from the start position and returns the deleted elements.

const months = ['Jan', 'March', 'April', 'June'];
const deletedmonths = months.splice(1, 1);

console.log('Remaining months');
console.table(months);
console.log('Deleted months');
console.table(deletedmonths);

Output

References:

Array.from()

Array.prototype.map()

Array.prototype.splice()

Conclusion

In this post we learned how we can create the chunks of array of a specified length from the given array.

TypeScript / JavaScript: Sort Object Array By Property

Let’s see how we can quickly sort TypeScript / JavaScript object array by property.

We will sort the array in following ways:

Consider following products array.

const products: Product[] = [
    { id: 1, name: 'Product 1', price: 100 },
    { id: 2, name: 'Product 2', price: 200 },
    { id: 3, name: 'Product 3', price: 300 },
    { id: 1, name: 'Product 1', price: 100 }
]

Sort the array by property in increasing order

Suppose we want to sort the array by price in increasing order.

We can use array sort method like following.

products.sort((prodA, prodB) => prodA.price > prodB.price ? 1 : -1);

console.table(products);

Output

Sort the array by property in decreasing order

Now let’s sort the products array by price in decreasing order.

products.sort((prodA, prodB) => prodA.price > prodB.price ? -1 : 1);

console.table(products);

Output

Array.prototype.sort()

Sort method sorts the elements of an array and returns the sorted array.

const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]

const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]

References:

Array.prototype.sort()

Conclusion

In this post we learned how we can sort the object array by property in ascending and descending order.

TypeScript / JavaScript: Remove Duplicates from Object Array using filter and findIndex method

Let’s see how we can efficiently remove the duplicates from the object array.

Consider the following products array.

const products: Product[] = [
    { id: 1, name: 'Product 1', price: 100 },
    { id: 2, name: 'Product 2', price: 200 },
    { id: 3, name: 'Product 3', price: 300 },
    { id: 1, name: 'Product 1', price: 100 }
]

This products array contains one duplicate product.

{ id: 1, name: 'Product 1', price: 100 }

We can remove the duplicates from object array using filter and findIndex array methods as following.

const prods = products.filter((value, index, array) => index == array.findIndex(item => item.id == value.id));

console.table(prods);

Output

Array.prototype.filter()

Filter method returns new array which passes the filter criteria.

const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]

Array.prototype.findIndex()

findIndex returns the index of the first element that satisfies the conditions, else returns -1.

const array1 = [5, 12, 8, 130, 44];

const isLargeNumber = (element) => element > 13;

console.log(array1.findIndex(isLargeNumber));
// expected output: 3

References:

Array.prototype.filter()

Array.prototype.findIndex()

Conclusion

In this post we learned how we can efficiently remove the duplicates from the object array.

Quick Reference – Ionic CLI Commands

In this post we will see some common Ionic CLI commands for Ionic app development.

Install Ionic CLI globally

Install Ionic CLI globally with npm.

npm install -g @ionic/cli

Ionic help

Get Ionic help.

ionic --help
ionic <command> --help
ionic <command> <subcommand> --help

Create a new Ionic Project

ionic start <name> <template> [options]

This command will create a new Ionic project.

Examples

ionic start
ionic start myapp
ionic start myapp tabs --type=angular

Build Ionic Project

ionic build [options]

ionic build will generate web assets for the Ionic project.

Examples

ionic build
ionic build --prod
ionic build --watch

Add Capacitor platform(s) to Ionic project

ionic capacitor add <platform>

ionic capacitor add will add Android or iOS Capacitor platform to the Ionic project.

Examples

Add Android

ionic capacitor add android

Add Ios

ionic capacitor add ios

Ionic Build for Android or iOS

ionic capacitor build <platform> [options]

ionic capacitor build will do the following:

  • Perform ionic build
  • Copy web assets into specified native platform.
  • Open IDE for native project, Xcode for iOS, Android Studio for Android.

Following command will ask user to select platform Android or iOS.

ionic capacitor build

Build for android

ionic capacitor build android

Build for iOS

ionic capacitor build ios

Open project in Android Studio

ionic capacitor open android

Copy web assets to native platforms

ionic capacitor copy [<platform>] [options]

ionic capacitor copy will do the following:

  • Perform ionic build, which compile web assets.
  • Copy web assets to Capacitor native platform(s).
  • This command will not open the IDE for respective platform.

Open IDE for a given native platform

ionic capacitor open <platform> [options]

This command will open the IDE for native project (Xcode for iOS, Android Studio for iOS).

Run Ionic project for platform

ionic capacitor run <platform> [options]

ionic capacitor run will do the following:

  • Build the ionic project.
  • Run the project in emulator (tested for Android).

Build and Copy project and then update native platform

ionic capacitor sync [<platform>] [options]

ionic capacitor sync will do the following:

  • Perform ionic build, which will generate web assets.
  • Copy web assets to Capacitor native platform(s).
  • Update Capacitor native platform(s) and dependecies.
  • Install and discovered Capacitor or Cordova plugins.

Examples:

For android

ionic capacitor sync android

For iOS

ionic capacitor sync ios

Update Capacitor native platforms, install Capacitor/Cordova plugins

ionic capacitor update [<platform>] [options]

ionic capacitor update will do the following:

  • Update Capacitor native platform(s) and dependencies.
  • Install any discovered Capacitor or Cordova plugins.

Generate Icons for Capacitor project

cordova-res <platform> --skip-config --copy

Reference npm package

https://www.npmjs.com/package/cordova-res

Expected project structure

resources/
├── icon.png
└── splash.png
config.xml
  • resources/icon.(png|jpg) must be at least 1024×1024px
  • resources/splash.(png|jpg) must be at least 2732×2732px
  • config.xml is optional. If present, the generated images are registered accordingly

Conclusion

In this tutorial we learned what are the common commands for Ionic project development.

Debug NodeJS TypeScript Using Visual Studio Code

Let’s see how we can configure our NodeJs project with TypeScript in Visual Studio Code for debugging.

Following are the steps:

Create project folder

Create project folder from the command prompt.

mkdir counter

Switch to project.

cd counter

Initialize project with npm package.json

npm init -y

Install TypeScript

npm i typescript --save-dev

Create tsconfig.json file

npx tsc --init --sourceMap --rootDir src --outDir lib

Here our source folder is src and output folder is lib.

Open the project in VS Code.

code .

You will see the project structure like this in VS Code.

and tsconfig.json file with specified options.

Add TypeScript source file

Create source code folder src, we specified the src as root folder in configurations.

And add file index.ts, with some code.

Create tasks.json file

Press Ctrl+Shift+P

Select Tasks: Configure Default Build Task

Then select tsc:watch – tsconfig.json

This will create a tasks.json file in .vscode folder.

Now build project, press Ctrl+Shift+B

This will generate the lib folder, which is our output directory.

and because of watch configuration build will keep running in the background and watch file changes.

Create launch.json file

Click on debug > create a launch.json file.

Choose node.js from options.

This will create a launch.json will

Finally Debug

Now go to your source file you want to debug, and press F9 on line you want to add a breakpoint.

Hit F5, and execution will pause at the breakpoint.

Congrats! you are able to debug your TypeScript now in VS Code.

Shortcut keys for debugging in VS Code.

  • Continue (F5)
  • Step Over (F10)
  • Step Into (F11)
  • Step Out (Shift+F11)
  • Restart (Ctrl+Shift+F5)
  • Stop (Shift + F5)

Conclusion

In this tutorial we learned how we can configure NodeJs TypeScript project in VS Code for easy debugging.

We have also seen what are some of the shortcut keys for quick debugging.

Please share your feedback or any query you have.

Firebase | Testing Firebase Cloud Function Locally with Cloud Function Emulator

Firebase CLI provides a cloud function emulator which can be used to run the Firebase Cloud Function locally before deploying to production. Following are the types of functions which can be emulated.

  • HTTP functions
  • Callable functions
  • Background functions triggered from Authentication, Realtime Database, Cloud Firestore, and Pub/Sub.

We will test a simple http function which we created in the last post.

Creating a Cloud Function Using Firebase CLI and TypeScript.

Following are the steps we will follow:

Install or Update the Firebase CLI

Firebase emulator is included in Firebase CLI, so we need to install it, or update it to the latest version.

npm install -g firebase-tools

Setting Up Admin Credentials for Emulated Functions

If your cloud function requires interaction with Google API or Firebase API via the Firebase Admin SDK then you may need to setup the admin credentials.

Go to the Service Accounts in Google Cloud Platform, under your project.

Select the service account row with Name “App Engine default service account“, and click on Actions button at the right end.

Select Manage Keys.

Click on Add Key drop down button.

Select Create new key.

This will open a modal window.

Choose JSON, from the available key types. This will generate and download the key in json file with key details.

JSON key file will look like following, values are omitted here.

{
  "type": "",
  "project_id": "",
  "private_key_id": "",
  "private_key": "",
  "client_email": "",
  "client_id": "",
  "auth_uri": "",
  "token_uri": "",
  "auth_provider_x509_cert_url": "",
  "client_x509_cert_url": ""
}

Set Google Application Credentials to the JSON file path.

This is required to authenticate to Google API or Firebase API from Firebase Admin SDK.

Execute following from project’s root directory.

set GOOGLE_APPLICATION_CREDENTIALS=path\to\key.json

Run the Firebase Emulator

Now we are ready to start the emulator.

Start the emulator by following command

firebase emulators:start

Emulator will be started and will provide you the function URL.

Call Function URL

Click on provide function URL, and you will receive the response from your function.

Great! We are able to run function locally.

Firebase Emulator UI

You will also be presented with Emulator UI URL.

Open the emulator UI URL in the browser.

In the Emulator screen you will be able to see all the different types of emulators.

You can navigate to Logs, to see any logging by function.

Modify and Test Local Cloud Function

Now let’s update the function.

Change the function response message.

Build the function again, and execute the following from functions folder.

npm run build

Reload the function URL provide by the running emulator and you will see updated response from local function.

When you are happy, you can deploy the function to Firebase as explained in this post.

Firebase | Creating a Cloud Function Using Firebase CLI and TypeScript

Conclusion

The Firebase emulator, which is included in the Firebase CLI, let’s us test the function locally before deploying to the cloud.

In this post we started with installing Firebase CLI and then we setup the Google Account Credential. Google Account Credential requires a JSON file with private key, which was generated in the Google Cloud Platform. Then we started the Firebase emulator and browsed the local function URL and received response from the local function.

Hope you liked this, please share your feedback or any query.

Firebase | Creating a Cloud Function Using Firebase CLI and TypeScript

Overview

Firebase cloud functions let’s you run a piece of code in cloud without managing the servers. This is quite helpful when you just want to manage your code and not to worry about the servers executing the code. This pattern is also known as serverless architecture.

These cloud functions can be triggered by multiple events such as an http request, scheduled time or in response to changes in Realtime Database and perform the intended job.

In this post we will see how we can create a simple Firebase cloud function using Firebase CLI and then deploy it to Firebase. We will use TypeScript to write the function.

Steps for creating the Cloud Function

Let’s create and deploy a Firebase cloud function.

Installing Firebase CLI

Firebase cloud functions are created and deployed using Firebase CLI, so let’s install the Firebase CLI globally. Type following command on command prompt.

npm install -g firebase-tools

Login to Firebase CLI

We need to authenticate to Firebase to create and deploy cloud functions, authenticate to Firebase using following command.

firebase login

This will open a browser window to authenticate.

If you are logged in with another account then you can logout first using following.

firebase logout

Choose the account to login.

Allow, to grant permissions to Firebase CLI.

On Allow following success screen will be presented.

And in command prompt message like following will be logged.

Creating a Firebase Cloud Function Project

Create a directory for the project.

mkdir firebase-function-demo

Change to project directory.

cd firebase-function-demo

Open the directory with Visual Studio code or any other editor.

code .

Initialize Firebase functions project

firebase init functions

Accept the confirmation.

Choose the appropriate option for you. In my case I chose “Use an existing project“, because I have already created the Firebase project.

Next I chose the project from the presented list.

For this example we are going to use the TypeScript, so choose the TypeScript.

Choose Y if you want to use ESLint.

Select Y to install the dependencies.

Your project structure should appear like this so far.

Creating a Cloud Function

We will use the sample helloworld cloud function created by the Firebase CLI for this example.

Open selected index.ts.

index.ts contains commented sample function.

Uncomment the code, and save the file.

File contains one sample http request based cloud function. Which will log following.

"Hello logs!", {structuredData: true}

and return following response.

"Hello from Firebase!"

In the same file more functions can be added, for example we can add another scheduled function like following.

export const scheduledJob = functions.pubsub.schedule("every 5 minutes")
    .onRun(()=>{
      console.log("This will be run every 5 minutes.");
      return null;
    });

This scheduled function will run every five minutes,

cron expression can be added like following to define trigger time for scheduled functions.

export const  scheduledFunctionCrontab = functions.pubsub.schedule('5 11 * * *')
  .timeZone('America/New_York') // Users can choose timezone - default is America/Los_Angeles
  .onRun((context) => {
  console.log('This will be run every day at 11:05 AM Eastern!');
  return null;
});

Deploying cloud function

Let’s deploy the sample code in index.ts to cloud.

Execute the following command on command prompt.

firebase deploy

On successful function deployment, function url will be provided.

Paste the URL in the browser.

and you will get the response like below from cloud function.

Great! Our cloud function is successfully deployed and responding to http request.

Navigate to Firebase project and select functions.

and you should be able to see your cloud function.

You can switch to Logs tab to see the logs of the cloud function.

Congratulations! We have just deployed our first simple cloud function.

Conclusion

In this post we learned how we can create a Firebase Cloud Function and deploy to Firebase. We started with how to install the Firebase CLI globally, and how to authenticate to it. Then we created a template project for cloud function using Firebase CLI and then deployed and tested the cloud function.

Hope you like this!

Please leave your feedback or any query you have.

Authenticating to ASP.NET Core Web Application Using Azure AD B2C

Azure Active Directory B2C enables users to authenticate themselves to applications using local accounts or social accounts such as Google, Facebook or LinkedIn.

The applications leveraging the Azure AD B2C, don’t have to maintain the authentication mechanism. All of that complexity will be handled by Azure AD B2C.

In this post we will see how to configure Azure AD B2C from scratch for ASP.NET Core applications.

We will go through the following topics:

  • Creating a new Azure AD B2C Tenant
  • App registration in Azure AD B2C Tenant
  • Configuring User Flows
  • Creating ASP.NET Core Web application Using Visual Studio 2019 and Configuring Azure AD B2C
  • Creating ASP.NET Core Web application Using .NET CLI and Configuring Azure AD B2C

To configure the Azure AD B2C for the applications first we need to create the Azure AD B2C tenant. Let’s create a new Azure AD B2C tenant.

Creating a New Azure AD B2C Tenant

To create a new Azure AD B2C tenant, login to your Azure portal and click on Create a resource.

In Create a resource page search for Azure Active Directory B2C in the search box, and select the first option available as shown below.

You will be navigated to Azure Active Directory B2C resource page.

Click on Create to create the Azure AD B2C tenant. This will create a separate tenant from your Azure AD tenant.

In the next screen you will be presented with following two options:

  • Create a new Azure AD B2C Tenant.
  • Link an existing Azure AD B2C Tenant to my Azure subscription.

Let’s choose Create a new Azure AD B2C Tenant to create a new tenant.

Next enter the following details for the new tenant.

  • Organization name: provide an organization name.
  • Initial domain name: provide a unique initial subdomain name.
    • Note down this initial domain name, we will need this to update in ASP.NET appsettings.json.
  • Country/Region: Select the country/region closest to your customers.
  • Subscription: Select subscription for your Azure AD B2C tenant.
    • Resource group: Choose resource group to contain Azure AD B2C tenant.

Then click on Review + Create

Validation screen will be presented.

Click on Create

You may encounter the following error.

The subscription is not registered to use namespace ‘Microsoft.AzureActiveDirectory’. See https://aka.ms/rps-not-found for how to register subscriptions. 

If you get this error then check the following post how to fix this error and then continue from here.

The subscription is not registered to use namespace ‘Microsoft.AzureActiveDirectory’

After fixing the error try creating Azure AD B2C Tenant again, and should be successful this time. You should be able to see the status under notifications.

Go to your newly created Azure AD B2C Demo tenant.

App Registration

Any application which needs to authenticate using Azure AD B2C, requires app registration in Azure.

Let’s register an app for our ASP.NET core application.

Click on New registration button inside the App registrations under our newly created Azure AD B2C tenant.

Fill in the details for the app registration

  • The display name: Enter any display name to easily identify the app.
  • Supported account types: choose “Accounts in any identity provider or organizational directory (for authenticating users with user flows)”
  • Redirect URI: Select Web in dropdown and enter following url in text box
https://localhost:5001/signin-oidc

Note the port no. we have provided 5001, you may need to update according to your application port no., we will see later in this post where in ASP.NET core application port can be configured.

Register the application.

In few seconds the app will be registered and you will be redirected to your App.

Note down the Application (client) ID, we will need this to update in ASP.NET core web application’s appsettings.json file.

Authentication options

Next we need to configure the authentications options.

Select the Authentication blade from left menu in registered app and check the two authentication options as shown below and click on Save.

We have successfully configured the app now.

Next we need to configure the User Flows for Sign up/ Sign in forms.

Configuring User Flows

User flows defines the sign up / sign in process for the applications but managed in Azure AD B2C. We can configure what data will be collected from the user and passed to the application.

To configure the User Flows, go back to the Azure AD B2C tenant and click on User Flows in left navigation.

Then click on New user flow

Selecting User Flow Type

In the new User Flow we get multiple options to configure, such as Sign up, Sign in, Profile editing.

Select the Sign up and sign in for this tutorial, this will enable the sign up and sign in experience for our web application.

On selecting Sign up and Sign in, it will enable another two options. Keep default and Click on Create

In the next screen provide a name for the User Flow and select email signup.

We can configure the Multifactor authentication as well, but leave default for now.

Scroll down a bit and select Show more…

On clicking show more, multiple fields will be presented to choose from in two columns Collect Column and Return Column.

Collect Column: Collect column shows what data will be collected from the user.

Return Claim: Return claim show what claims will be passed back to the application.

Select following options for our application and then click OK.

Note we have selected Display Name in collect attribute, during sign up user will be asked for Display Name.

Click on Create.

User Flow will be created and will be available under User flows.

Creating ASP.NET Core Web Application Using Visual Studio 2019 and Configuring Azure AD B2C

Let’s create an ASP.NET core application, and then we will configure it for Azure AD B2C authentication.

Open Visual Studio and select on Create a new project.

Select ASP.NET Core Web App (Model-View-Controller) for this example and click on next.

Provide project name and location, and select Next.

Select Microsoft Identity Platform from Authentication Type and click on create.

You may be presented with following screen to install required components (dotnet msidentity pool), select Finish to install.

ASP.NET application will be created.

Updating Azure AD B2C configurations

Open the appsettings.json you will see the following configurations.

{
/*
The following identity settings need to be configured
before the project can be successfully executed.
For more info see https://aka.ms/dotnet-template-ms-identity-platform 
*/
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "qualified.domain.name",
    "TenantId": "22222222-2222-2222-2222-222222222222",
    "ClientId": "11111111-1111-1111-11111111111111111",
    "CallbackPath": "/signin-oidc"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Replace it with following and replace {Initial Domain Name} and {Application (Client) Id} with values we noted earlier.

{
/*
The following identity settings need to be configured
before the project can be successfully executed.
For more info see https://aka.ms/dotnet-template-ms-identity-platform 
*/
  "AzureAd": {
    "Instance": "https://{Initial Domain Name}.b2clogin.com/",
    "ClientId": "{Application (Client) Id}",
    "Domain": "{Initial Domain name}.onmicrosoft.com",
    "SignedOutCallbackPath": "/signout/B2C_1_susi",
    "SignUpSignInPolicyId": "b2c_1_susi",
    "ResetPasswordPolicyId": "b2c_1_reset",
    "EditProfilePolicyId": "b2c_1_edit_profile",
    "CallbackPath": "/signin-oidc"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Updating application Port no.

Remember earlier we specified port no. 5001 in Azure for callback Url?

Let’s update this in our ASP.NET project.

Open Properties > launchSettings.json

Update sslPort no. to 5001.

 "sslPort": 5001

If you want to keep another port no. then make sure you update in Azure AD B2C app registration too.

Testing Azure AD B2C

Press F5 and you will be redirected to {orgname}.b2clogin.com for authentication, If not then click on Sign in link on web portal.

Click on Sign up, and you will be asked for sing up details along with Display name we configured earlier in User Flow.

Creating ASP.NET Core Web application Using .NET CLI and Configuring Azure AD B2C

Open command prompt.

Create a directory for the web application.

mkdir AzureADB2CCodeDemo

Switch to the directory just created.

cd AzureADB2CCodeDemo

Create new dotnet mvc application project with Azure AD B2C option, i.e. IndividualB2C

dotnet new mvc --auth IndividualB2C

Open the project with Visual Studio Code.

Code .

Open appsettings.json, you will see similar options as we saw previously with Visual Studio 2019.

{
  "AzureAdB2C": {
    "Instance": "https://login.microsoftonline.com/tfp/",
    "ClientId": "11111111-1111-1111-11111111111111111",
    "Domain": "qualified.domain.name",
    "SignedOutCallbackPath": "/signout/B2C_1_susi",
    "SignUpSignInPolicyId": "b2c_1_susi",
    "ResetPasswordPolicyId": "b2c_1_reset",
    "EditProfilePolicyId": "b2c_1_edit_profile",
    "CallbackPath": "/signin-oidc"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Replace it with following and replace {Initial Domain Name} and {Application (Client) Id} with values we noted earlier.

{
/*
The following identity settings need to be configured
before the project can be successfully executed.
For more info see https://aka.ms/dotnet-template-ms-identity-platform 
*/
  "AzureAd": {
    "Instance": "https://{Initial Domain Name}.b2clogin.com/",
    "ClientId": "{Application (Client) Id}",
    "Domain": "{Initial Domain name}.onmicrosoft.com",
    "SignedOutCallbackPath": "/signout/B2C_1_susi",
    "SignUpSignInPolicyId": "b2c_1_susi",
    "ResetPasswordPolicyId": "b2c_1_reset",
    "EditProfilePolicyId": "b2c_1_edit_profile",
    "CallbackPath": "/signin-oidc"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Updating application Port no.

Let’s update the port for project generated from .NET CLI.

Open Properties > launchSettings.json

Update sslPort no. to 5001. as highlighted below.

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:51430",
      "sslPort": 44315
    }
  },
  "profiles": {
    "AzureADB2CCodeDemo": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

Run project

dotnet run

And you should see following from b2clogin.com

Conclusion

In this post we learned how to configure Azure AD B2C for ASP.NET Core applications to allow users to authenticate themselves leveraging Azure AD B2C capabilities. Azure AD B2C let’s users to use local account or social accounts such as Google, Facebook or LinkedIn for authentication.

We started by setting up the new Azure AD B2C tenant and registered app for ASP.NET core application. Then we configured User Flow for Sign up and Sign In. Next we configured Azure AD B2C settings in ASP.NET core applications created using Visual Studio 2019 UI and .NET CLI.

Please leave your feedback or any queries you have.

Thanks!