Använd anpassad kod i ett anpassat anslutningsprogram

Anpassad kod omvandlar nyttolaster för begäran och svar utöver vad befintliga principmallar omfattar. När du använder kod har den företräde framför den kodlösa definitionen.

Mer information finns i Skapa en anpassad anslutning från grunden.

Skriptklass

Koden måste implementera en metod som heter ExecuteAsync, som körs under körningen. Du kan skapa andra metoder i den här klassen efter behov och anropa dem från ExecuteAsync metoden. Klassnamnet måste vara Script och måste implementera ScriptBase.

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

Definition av stödklasser och gränssnitt

Klassen Script refererar till följande klasser och gränssnitt. Använd dem för lokal testning och kompilering.

public abstract class ScriptBase
{
    // Context object
    public IScriptContext Context { get; }

    // CancellationToken for the execution
    public CancellationToken CancellationToken { get; }

    // Helper: Creates a StringContent object from the serialized JSON
    public static StringContent CreateJsonContent(string serializedJson);

    // Abstract method for your code
    public abstract Task<HttpResponseMessage> ExecuteAsync();
}

public interface IScriptContext
{
    // Correlation Id
    string CorrelationId { get; }

    // Connector Operation Id
    string OperationId { get; }

    // Incoming request
    HttpRequestMessage Request { get; }

    // Logger instance
    ILogger Logger { get; }

    // Used to send an HTTP request
    // Use this method to send requests instead of HttpClient.SendAsync
    Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken);
}

Exempel

Hej Världen-skript

Det här exempelskriptet returnerar alltid Hello World som svar för alla begäranden.

public override async Task<HttpResponseMessage> ExecuteAsync()
{
    // Create a new response
    var response = new HttpResponseMessage();

    // Set the content
    // Initialize a new JObject and call .ToString() to get the serialized JSON
    response.Content = CreateJsonContent(new JObject
    {
        ["greeting"] = "Hello World!",
    }.ToString());

    return response;
}

Regex-skript

Följande exempel tar en textsträng som ska matchas och det reguljära uttrycket och returnerar matchningsresultatet i svaret.

public override async Task<HttpResponseMessage> ExecuteAsync()
{
    // Check if the operation ID matches what is specified in the OpenAPI definition of the connector
    if (this.Context.OperationId == "RegexIsMatch")
    {
        return await this.HandleRegexIsMatchOperation().ConfigureAwait(false);
    }

    // Handle an invalid operation ID
    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.BadRequest);
    response.Content = CreateJsonContent($"Unknown operation ID '{this.Context.OperationId}'");
    return response;
}

private async Task<HttpResponseMessage> HandleRegexIsMatchOperation()
{
    HttpResponseMessage response;

    // We assume the body of the incoming request looks like this:
    // {
    //   "textToCheck": "<some text>",
    //   "regex": "<some regex pattern>"
    // }
    var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false);

    // Parse as JSON object
    var contentAsJson = JObject.Parse(contentAsString);

    // Get the value of text to check
    var textToCheck = (string)contentAsJson["textToCheck"];

    // Create a regex based on the request content
    var regexInput = (string)contentAsJson["regex"];
    var rx = new Regex(regexInput);

    JObject output = new JObject
    {
        ["textToCheck"] = textToCheck,
        ["isMatch"] = rx.IsMatch(textToCheck),
    };

    response = new HttpResponseMessage(HttpStatusCode.OK);
    response.Content = CreateJsonContent(output.ToString());
    return response;
}

skript för vidarebefordran

I följande exempel vidarebefordras den inkommande förfrågan till serverdelen.

public override async Task<HttpResponseMessage> ExecuteAsync()
{
    // Check if the operation ID matches what is specified in the OpenAPI definition of the connector
    if (this.Context.OperationId == "ForwardAsPostRequest")
    {
        return await this.HandleForwardOperation().ConfigureAwait(false);
    }

    // Handle an invalid operation ID
    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.BadRequest);
    response.Content = CreateJsonContent($"Unknown operation ID '{this.Context.OperationId}'");
    return response;
}

private async Task<HttpResponseMessage> HandleForwardOperation()
{
    // Example case: If your OpenAPI definition defines the operation as 'GET', but the backend API expects a 'POST',
    // use this script to change the HTTP method.
    this.Context.Request.Method = HttpMethod.Post;

    // Use the context to forward/send an HTTP request
    HttpResponseMessage response = await this.Context.SendAsync(this.Context.Request, this.CancellationToken).ConfigureAwait(continueOnCapturedContext: false);
    return response;
}

Vidarebefordra och omvandla skript

I följande exempel vidarebefordras den inkommande förfrågan och svaret som returneras från serverdelen omvandlas.

public override async Task<HttpResponseMessage> ExecuteAsync()
{
    // Check if the operation ID matches what is specified in the OpenAPI definition of the connector
    if (this.Context.OperationId == "ForwardAndTransformRequest")
    {
        return await this.HandleForwardAndTransformOperation().ConfigureAwait(false);
    }

    // Handle an invalid operation ID
    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.BadRequest);
    response.Content = CreateJsonContent($"Unknown operation ID '{this.Context.OperationId}'");
    return response;
}

private async Task<HttpResponseMessage> HandleForwardAndTransformOperation()
{
    // Use the context to forward/send an HTTP request
    HttpResponseMessage response = await this.Context.SendAsync(this.Context.Request, this.CancellationToken).ConfigureAwait(continueOnCapturedContext: false);

    // Do the transformation if the response was successful, otherwise return error responses as-is
    if (response.IsSuccessStatusCode)
    {
        var responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false);
        
        // Example case: response string is some JSON object
        var result = JObject.Parse(responseString);
        
        // Wrap the original JSON object into a new JSON object with just one key ('wrapped')
        var newResult = new JObject
        {
            ["wrapped"] = result,
        };
        
        response.Content = CreateJsonContent(newResult.ToString());
    }

    return response;
}

Namnutrymme som stöds

Alla C#-namnutrymme stöds inte. Du kan för närvarande endast använda funtkioner från följande namnrymder:

Viktigt!

Den .NET version som stöds för närvarande är .NET Standard 2.0.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using System.Xml.Linq;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

GitHub-exempel

För exempel i DocuSign-anslutningsprogrammet, gå till Power Platform Connectors på GitHub.

Vanliga frågor och svar om anpassad kod

Mer information om anpassad kod finns i Steg 4: (Valfritt) Använd anpassat kodstöd.

F: Kan jag använda flera skript per anpassad anslutningsapp?S: Nej, du kan bara använda en skriptfil per anpassad anslutningsapp.

F: Jag får ett internt serverfel när jag uppdaterar min anpassade anslutning. Vad kan vara problemet? S: Det är troligtvis ett problem med att kompilera koden. I framtiden visar systemet den fullständiga listan över kompileringsfel för att förbättra den här upplevelsen. För tillfället använder du de stödande klasserna för att testa kompileringsfel lokalt som en lösning.

F: Kan jag lägga till loggning i min kod och hämta en spårning för felsökning?S: Inte för närvarande, men stöd för den här funktionen kommer att läggas till i framtiden.

F: Hur kan jag testa min kod under tiden?S: Testa den lokalt och se till att du kan kompilera kod med hjälp av endast de namnområden som anges i namnområden som stöds. Information om lokal testning finns i Skriva kod i en anpassad anslutningsapp.

F: Finns det några gränser?S: Ja. Skriptet måste slutföra körningen inom 2 minuter och storleken på skriptfilen får inte överstiga 1 MB. Den här nya tidsgränsen på 2 minuter gäller för alla nyligen skapade anpassade anslutningsappar. För befintliga anpassade anslutningsappar måste du uppdatera anslutningsappen för att den nya tidsgränsen ska börja gälla.

F: Kan jag skapa min egen HTTP-klient i skriptkod?S: För närvarande ja, men systemet blockerar den här funktionen i framtiden. Det rekommenderade sättet är att använda detta. Context.SendAsync-metod .

F: Kan jag använda anpassad kod med den lokala datagatewayen?S: Inte för närvarande, nej.

Stöd för Virtual Network

När du använder anslutningsappen i en Power Platform-miljö som är länkad till ett virtuellt nätverk gäller följande begränsningar:

  • Context.SendAsync använder en offentlig slutpunkt så att den inte kan komma åt data från privata slutpunkter i det virtuella nätverket.

Allmänna kända problem och begränsningar

I vissa regioner returneras rubriken OperationId i base64-kodat format. Om implementeringen kräver OperationId värdet avkodar base64 det för användning.

public override async Task<HttpResponseMessage> ExecuteAsync()
{
    string realOperationId = this.Context.OperationId;
    // Resolve potential issue with base64 encoding of the OperationId
    // Test and decode if it's base64 encoded
    try {
        byte[] data = Convert.FromBase64String(this.Context.OperationId);
        realOperationId = System.Text.Encoding.UTF8.GetString(data);
    }
    catch (FormatException ex) {}
    // Check if the operation ID matches what is specified in the OpenAPI definition of the connector
    if (realOperationId == "RegexIsMatch")
    // Refer to the original examples above for remaining details
}

Gå vidare

Skapa en anpassad anslutning från grunden

Ge feedback

Vi uppskattar feedback på problem med vår anslutningsplattform eller nya funktioner. Om du vill ge feedback går du till Skicka in problem eller få hjälp med anslutningsappar och väljer typ av feedback.