Using custom C# code when creating Custom Connectors for Power Platform or Logic Apps

If you’re doing integrationw between Dynamics 365 Business Central or other applications and the Power Platform, I think that sometimes you have the need to create a custom connector.

Custom connectors are useful when you don’t have a pre-built connector with a particular application or API and they permit you to create (and even share) a connector with its own triggers and actions. They’re notyhing more than a wrapper around a REST API (Logic Apps also supports SOAP APIs) that allows Logic Apps, Power Automate, or Power Apps to communicate with that REST or SOAP API.

Custom connectors are used the same way Microsoft-managed connectors are used. You’ll need to create a connection to your API in order to use that connection to call any operations that you’ve exposed in your custom connector.

Connectors created in Power Automate are available in Power Apps. Likewise, connectors created in Power Apps are available in Power Automate. This isn’t true for connectors created in Logic Apps. However, you can reuse the OpenAPI definition or Postman collection to recreate the connector in any of these services. 

If you’re a custom connector creator, there’s an important news to share: you have now the support for adding custom C# code in connectors. This feature (actually in public preview at the time of writing this post) will enable connector developers to use custom logic to send external requests and enable complex transformations for responses (you can manipulate requests and responses of your connector).

How to do that?

You need to create a C# class called Script that inherits from ScriptBase and that implements a method called ExecuteAsync, called during the runtime of the connector, like the following:

public class Script : ScriptBase
{
    public override Task<HttpResponseMessage> ExecuteAsync()
    {
        // Your custom code here
    }
}

You can create other methods in this class as neededmand call them from ExecuteAsync method. In the ExecuteAsync method you can access the input and output data of your request and make the data manipulation you want.

This is an example of a data manipulation script, where I can modify things on the incoming request (before calling the real API) and on the API response (before returning it):


public class Script : ScriptBase
{
    public override async Task<HttpResponseMessage> ExecuteAsync()
        {
            // Manipulate the request data before sending it
            var requestContentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false);
            var requestContentAsJson = JObject.Parse(requestContentAsString);
            this.Context.Request.Content = HandleJsonRequestContent(requestContentAsJson.ToString());

            // Sending the connector API request
            var response = await this.Context.SendAsync(this.Context.Request, this.CancellationToken).ConfigureAwait(continueOnCapturedContext: false);
            
            // Manipulate the response data before returning it
            var responseContentAsString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            var responseContentAsJson = JObject.Parse(responseContentAsString);
            response.Content = HandleJsonResponseContent(responseContentAsJson.ToString());

            return response;
        }
}

Imagine to have an API that gives the following JSON response to the connector:

string json = @"{
  'order': {
    'customerNo': 'c001',
    'customerName': 'Customer 1',
    'sellToAddress': 'Road 21, Milan - Italy',
    'internalId': 'ID003456',
    'items': []
  }
}";

In the above HandleJsonResponseContent function you could do something like the following:

var responseContentAsJson = JObject.Parse(json);

JObject order = (JObject)responseContentAsJson["order"];

order["customerNo"] = ((string)order["customerNo"]).ToUpper();
order.Property("internalId").Remove();

order.Property("sellToAddress").AddAfterSelf(new JProperty("orderSource", "Web Shop"));

JArray items = (JArray)order["items"];
items.Add("Item 1");
items.Add("Item 2");

and your final JSON response from the connector will be:

{
  'order': {
    'customerNo': 'C001',
    'customerName': 'Customer 1',
    'sellToAddress': 'Road 21, Milan - Italy',
    'orderSource': 'Web Shop',
    'items': [
       "Item 1",
       "Item 2"
     ]
  }
}

How to execute this script code from your custom connector?

When creating a custom connector, you will have now a new Code tab, with a predefined template:

You can copy and paste your custom code ((or upload a .cs or .csx file too). Then, select the toggle next to Code Disabled to enable your code:

You can then select the actions and triggers where to apply your custom code. If no operation is selected, it’s applied to all operations. Save the connector and you’re ready to go.

Why I think it will be a very useful feature?

Because by adding custom C# code you can for example:

  • validate incoming request and parameters
  • add hidden parameters to the incoming requests
  • manipulate the incoming request and make it more easy for the users of your connector
  • add additional data to the response of your connector
  • manipoulate the response of your connector and format it as per your needs
  • handle errors and/or format errors

Please also remember that:

  • Code must be written in C#.
  • Only one script file per custom connector is supported
  • Your script must finish execution within 5 seconds and the size of your script file can’t be more than 1 MB
  • Your script code must be tested locally

2 Comments

  1. In trying this example or even the default code provided I get this error “Encountered internal server error. The tracking Id is ‘8b8a4fde-29ca-41db-b34c-b5688688edc6’.” The code looks fine in visual studio. Is there additional setup or licensing required to get this functionality?

    Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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