---
source_url: https://itmustbecode.com/dataverse-custom-api-allowcustomprocessing-explained/
title: Dataverse Custom API: AllowCustomProcessing Explained
date: 2021-01-11T12:58:32+00:00
categories:
  - blog
tags:
  - custom-action
  - dataverse-customapi
word_count: 1133
reading_time_minutes: 6
type: posts
---

This is the first article in a series of posts aimed at showing the **main differences** between **Dataverse Custom API** s and the more traditional **Workflow Custom Actions**. This article will focus on the **AllowedCustomProcessingStep** attribute of Custom APIs.

## Custom API vs Custom Action

Dataverse **Custom APIs** and Workflow **Custom Action** share common ground. The 2 models will expose **custom Messages** that can be called by the **Dataverse WebApi** like other Out-of-the-Box Messages of the Platform (ex. Create, Update). The differences are found in the underlying implementation of each model.

> You can find Microsoft official documentation that compares the 2 models [**here**](https://docs.microsoft.com/en-us/powerapps/developer/data-platform/custom-actions?WT.mc_id=DX-MVP-5004959)

One of the most notable differences in my opinion is that with a **Custom API** you have the ability to **restrict** how 3rd Party developers can **mingle** with your custom Message by using the **AllowedCustomProcessingStepType** attribute.

But first, let's go under the hood and see how a Custom API works.

## Coding on the 30

If you are familiar with the Dataverse Message **execution pipeline** you know that there are **4 Stages** `PreValidation(10)`, `PreOperation(20)`, `MainOperation(30)` and `PostOperation(40)`. The **Main Operation (30)** is **reserved** for the platform core operation and has always been (until now) **obfuscated** to developers.

{{< figure src="./image-45.png" alt="" caption="" >}}

Then, a bit like a suckerfish that attaches itself to a shark, developers can **extend** the Messages by attaching plugin steps to stages before or after the Main operation to **alter** the message behavior.

That is exactly the strategy that can be used to execute custom code using classic **Workflow Custom Actions**. You would start by defining your Action, Inputs, and Outputs in the classic workflow designer and leave the (low-code) execution part blank. This would create a new Message on which you can attach custom code on Pre or Post Operation.

Things are a bit different with **Custom APIs**, where you are actually coding the Message **core operation** itself **,** and the custom code triggered by the API executes on the **Main Operation (30)**( _see Plugin trace below_).

{{< figure src="./image-36.png" alt="" caption="" >}}

> _As a Power Platform developer, I personally felt a **great deal of power**_ ⚡ _when I first realized that I was **coding on the 30**... but maybe I spend too much time in front of my computer_ 🤓 _._

In fact, with the **Custom API** model, you won't even need to register any plugin steps with the **Plugin Registration Tool** for the code to be executed. You only need to configure your Custom API record to point on a Plugin exposed by a plugin assembly. **Once this link** between the Custom API record and a Plugin Type is made, the API is up and running.

{{< figure src="./image-46.png" alt="" caption="" >}}

## To Allow or Not To Allow. That is the Question.

That being said, there is an attribute on the Custom API Table called **AllowedCustomProcessingStepType** that enables the author to configure how others will be able to attach or not to the Message exposed by the API. This attribute contains the following values.

1. **None**
   - This **blocks completely** any extension of the message
1. **AsyncOnly**
   - Only **asynchronous** plugins can be registered on the message
1. **SyncAndAsync**
   - Allows **any kind** of extensions on the message

This can be very important especially if the message being exposed by the Custom API carries sensitive information. _For example, a message that would expose the Licensing status of an ISV product._

### Let's illustrate this with an example

Say we have an Environment Variable called ' **SensitiveUrl**' that contains an URL that is critical to our business logic. A Custom API is responsible to retrieve the Environment variable value at run-time.

{{< figure src="./image-37.png" alt="" caption="" >}}

We have 2 Custom APIs that will execute the **exact same code**, but one has the **AllowedCustomProcessingStepType** set to **None** and the other set to **SyncAndAsync**.

Name**AllowedCustomProcessingStepType****GetEnvironementVariable**None**GetEnvironmentVariable\_OPEN**SyncAndAsync

{{< figure src="./image-48.png" alt="" caption="" >}}

{{< figure src="./image-47.png" alt="" caption="" >}}

> If you are interested, the **GetEnvironmentVariable** API implementation can be found in my collection of generic **[Dataverse Custom API](/2021/01/02/dataverse-custom-api-collection/)** _._

Now let's register a new Plugin Assembly on the Dataverse environment called **HackTheApi**. Since the **GetEnvironmentVariable\_OPEN** is **extendable** because of its **AllowedCustomProcessingStepType** status (SyncAndAsync), it is possible to attach to the message synchronously and execute a diabolic 😈 hack. ( _Overdramatization_ )

{{< figure src="./image-38.png" alt="" caption="" >}}

_Note that because of its AllowProcessingStep value set to **None**, the message **GetEnvironmentVariable** will not even appear in the list of available messages to extend._

The code of this nifty hack will substitute the value of the environment variable contained in the **OutputParameters** collection of the **PluginExecutionContext** with a different value.

{{< figure src="./image-39.png" alt="" caption="" >}}

When we test the APIs, we get completely different behavior.

**GetEnvironmentVariable** will give the expected result.

{{< figure src="./image-41.png" alt="" caption="" >}}

While **GetEnvironmentVariable\_OPEN** will return the ' **hacked value**'.

{{< figure src="./image-40.png" alt="" caption="" >}}

I'm being dramatic on purpose here but you can see that leaving an API opened could have a **significant impact** on your business logic _._ This doesn't mean that you should always block your APIs, it might be totally worth it and legit to allow Message extension in certain scenarios.

## Async Only

The 3rd option for the **AllowedCustomProcessingStepType** is to allow only **Asynchronous** plugin steps to be registered on the Custom API message.

Using this option will assure you that the **Outputs** of your API call **cannot be tampered** with while offering to 3rd party developers a way to trigger async custom code after a specific API has been called. _For example, every time an API is called, I want to increment a counter._

## Summary

There are differences in the way custom code is executed between the Custom API and the Custom Action extension model. A Custom API custom code executes on the **Main Operation** (30) of the message execution pipeline, something that is not possible in other extension models.

We demonstrated how the **AllowedCustomProcessingStepType** attribute can have a **significant impact** on the behavior of Custom API. This level of control is **only available** on the new Custom API functionality and doesn't exist for classic Workflow Custom Actions.

There is no Good or Bad way, every option has its pros and cons, and you need to understand the intent and the desired usage of your APIs before releasing them to the wild.

Happy **API**'ing!

## Links and references
{{< linkcard url="https://docs.microsoft.com/en-us/powerapps/developer/data-platform/custom-actions?WT.mc_id=DX-MVP-5004959" title="Create your own messages (Microsoft Dataverse) - Power Apps" summary="Learn about creating your own custom Microsoft Dataverse messages to be executed from your applications, and how these custom messages differ from using the Custom API feature." image="/linkcards/f69ad1e3eed32c06.png" domain="docs.microsoft.com" new_tab="true" nofollow="true" >}}


{{< linkcard url="https://github.com/drivardxrm/Dataverse-CustomApis" title="drivardxrm/Dataverse-CustomApis" summary="Collection of Dataverse Custom Apis. Contribute to drivardxrm/Dataverse-CustomApis development by creating an account on GitHub." image="/linkcards/e9ffe6985986dfe4.png" domain="github.com" new_tab="true" nofollow="true" >}}


{{< linkcard url="http://ptv.xrmtoolbox.com/" title="Plugin Trace Viewer for XrmToolBox" summary="The primary goal of the tool is to give developers and administrators of Microsoft Dynamics CRM an easy to use tool to investigate the Plugin Trace Log. This includes the possibility to filter the logs and display the information in ways not currently possible within the Micr…" image="/linkcards/672b89b7941617ef.png" domain="ptv.xrmtoolbox.com" new_tab="true" nofollow="true" >}}

{{< linkcard url="/customapi-manager-for-xrmtoolbox/" title="Custom API Manager for XrmToolBox" summary="Like most Power Platform developers, I am a heavy user of the XrmToolBox. This is the story of creating a tool to contribute to the community." image="./2021-01-03_19-53-32.png" domain="itmustbecode.com" new_tab="false" nofollow="false" >}}

