Instant Dataverse Functions & Low-Code Plug-ins
david wyatt

david wyatt @wyattdave

About: Microsoft MVP. Power Platform form Developer and White Hat. Passion for RPA and all things LowCode, back story in shadow IT through VBA. Plays with Chrome Extensions

Location:
Nottingham, UK
Joined:
Jun 21, 2021

Instant Dataverse Functions & Low-Code Plug-ins

Publish Date: Jun 9
7 4

This is the third in the series, so make sure you read the 101 and maybe the Automated blogs first.

Instant Dataverse Functions aka Instant Low-Code Plug-ins can be built in either of the studios (101 explains more), but there are a few differences, I will generally use the Plug-in to reference them and for my screenshots when there are no differences, but when there is I will show both.

  1. What Are Instant Functions / Plug-ins
  2. How to Create one
  3. The Code
  4. How to Call One
  5. Bugs
  6. Quick Example

1. What Are Instant Functions / Plug-ins

Instant plug-ins are kind of a limited version of Azure Functions. A small script that can be called by a api end point. They use Power FX as the coding language and can interact with Dataverse, and with Low-Code plug-ins also any normal connector.

They have limited run time and are designed to be 'bite size', so aren't good for complicated workflows, but are great for:

  • Anything reusable across Power Automate, Power Apps, Copilot Studio
  • Missing expressions from Power Automate
  • Interactions that are transactional (If interacting with Dataverse edits to the tables are only finalised when all edits succeed, if one fails all previous rollback)
  • High volume (uses 1 Power Platform API call)

2. How to Create one

Power FX Functions

These are now built into the PowerApps studio, so to create one open make.powerpapps.com. Click More from the bottom of the left menu, then Discover all, you should see them at the bottom.

Image description

From there you will see a list of your Functions, you can right click to edit, delte, copy snippet (for Power Apps) or Test.

To create a new Function click 'Create a function at the top.

functions

A side panel will open showing you the key information to enter

Low-Code Plug-ins

After installing the Dataverse Accelerator app goto make.powerapss, and view all Apps, you should see the Dataverse Accelerator App

Dataverse Accelerator App

Open the Model Driven app and you will see 4 options

  • Create instant plug-in (that's the one))
  • Create automated plug-in (Previous blog)
  • Plugin monitoring - run history of all plug-ins
  • API Explorer - test Dataverse API's, including instant plug-ins

Click on Create instant plug-in and you will see the build screen:

low-code plug-ins

Inputs

There are the following inputs:

Display Name

Your Plug-in, this is also its unique name, so cant have the same name as another plug-in (unlike Apps and Flows).

unique name

Description
Description of the Plug-ins, this is at the top in Dataverse Functions and a required field, but is in Advanced options and optional in Low-Code Plug-ins.

Parameters
This is what will be passed into and returned by the plug-in.

Image description

You can use:

  • Integer
  • Decimal
  • Float
  • Boolean
  • String
  • EntityReference (Dataverse Table)

As you can see there is no objects or arrays, so you cant pass json. But there is a workaround I will show you later.

Table reference
Again this is only for Dataverse Functions, not Low-Code Plug-ins. Here you select upto 5 tables you wish to reference in your code:

tables

For Low-Code Plug-ins you can reference more then 5 tables, you just type them in (not sure if there is a limit)

6 tables

Expression
This is the main coding input where the Power FX code is

Solution
Low-Code Plug-ins are solution aware, so can be added to a solution for ALM. Although you can add the plug-in to a solution later, by selecting here it is not only added but inherits the solutions publisher prefix.

Name
System name for the Plug-in, this has the solution prefix so change the solution to change prefix

Scope
Only for Low-Code Plug-ins, not Functions. This sets if the plug-in is bound to a specific table or global. If you select a table then an additional table selector will appear for you to select the table to bound to.

The main difference is when bound the api is expecting a record from the bound table to action (so similar to Automated Plug-ins).

Bound table
bound table

Unbound (Global)
unbound table

Please not once saved you can not change from bound to unbound

3. The Code

As stated there are inputs and outputs, once added you can referene the inputs by simply typing them in.

If you are returning a response then the code block should be within {}, with the output set with 'outputName:'

expression window

So above you can see Number is our out parameter and the Sides input is used with the RandBetween() function.

You cant Set() variables in Low-Code Plug-ins, but you can use With(), which allows some basic variable holding.

with

YOu can use most Power FX functions, including Patch(), Filter(), ForAll(), MAtch(), etc.

If you are bounding to a table you can use the 'NewRecord' to reference record passed.

To use other connectors, not just Dataverse, click the connectors icon in the top right and find the connection reference you want to use.

connections
This is only available in Low-Code Plug-ins, not in Functions

Click Copy to add the snippet, and then paste into the code where you want to use it. Just like in a Power App intellisense will help with the inputs.

intelisense

And now when the plug-in is called it will use the connection in the connection reference to send an email.

send email

4. How to Call One

As there are really just an API call, in theory be called anywhere, but I wanted to show you the main 3

Power Automate

Custom APIs with Dataverse can be called using the UnBound action in Power Automate.

Simpy add the 'Perform an unbound action' (either local or different environment, though remember the Plug-in is scoped to the environment it is in), then search for the plug-in by name. You will see all standard plug-ins, include ones build by Microsoft like exportSolution, so the list is quite long.

unbound

If you are scoped to a table then the plug-in is now bound, so you need to use the bound version of the Dataverse action.

bound

Canvas Power App

To use the plug-in in a Canvas App you have 2 stages, copy the code and add Dataverse as Datasource.

To copy the code is slightly different in Plug-ins vs functions.

Plug-ins
plug-in snippet

Functions

Image description

Adding datasource is a simple as adding any dataverse table, just select Environment as the table.

add data

Now simply paste the snippet in your code where you want the plug-in to run and update the variable.

button runn

API (Postman)

All plug-in calls are POST, even if you are only doing a GET.

The URL should be like below:

https://{{yourDynmicsUyl}/api/data/v9.1/{yourPluginName}
Enter fullscreen mode Exit fullscreen mode

You can find the url and name in the test response in @odata.context key, just don't use that actual url as its the metadata, and remove the word 'Response' from end of the name.

postman

5. Bugs

Just like automated, there are still a few. The ones I see often are:

Parameters not showing but being sent

parameter error

Connection Issues
There are lots of issues when using different connections, SharePoint is a good example; As its all dynamic, with everytable different, it cant read the schema, so it wont save as it doesnt recognise field names. And even when no field names are referenced it still fails.

get items code

get items error

Failure to Save
This one is super frustrating, as you will hit save and it will show success bar, but when you reload none of your changes have been saved (so always do a copy paste to notepad!).

6. Quick Exampleu

I wrote this a while back in a community blog, the below code extracts the error message from a Power Automate Scope exception catch

{ReturnMessage:
    Concat(
        Filter(
            Split(
                Substitute(Concat(MatchAll(ExceptionJSON,"essage'[^}]*\'"),FullMatch&"|")
            ,
                "essage"
            ,
                "'message"
            )
        ,
            "|"
        )
     ,
        !("is skipped" in Value) And !("No dependent actions succeeded" in Value)
    )
,
    Value
,
    "|"
)
Enter fullscreen mode Exit fullscreen mode

exception code

We set the ReturnMessage, {ReturnMessage:}, then use a regex essage'[^}]*\' to find the error messages in the error json (we converted it to a string in the flow).

We then turn them into a pipe dilemata array (but still a string).

As we used message to split we replace them with 'message, so that we can parse it back.

Next we turn back to an array by splitting at the pipe, and filter out all of the unnecessary messages, before finally concating back into a pipe dilemata array.

And that's the workaround around arrays, we have to build them as a string and pass them back and let the App,Flow,API parse them back.


So that's a quick intro to Low-Code Plug-ins, I only have 3 planned so far, but I'm sure more will come, join my mailing list if you would like to be notified when I realise my next blog (I cover all things Power Platform).

Comments 4 total

Add comment