Dela via


Skriva kod i ett anpassad anslutningsprogram

Med anpassad kod omvandlas begärans- och svarsnyttolaster utanför omfånget för befintliga principmallar. När kod används får den prioritet framför den kodlös definitionen.

Mer information: Skapa en anpassad anslutningsapp från grunden

Skriptklass

Koden måste implementera en metod som kallas ExecuteAsync, som anropas under körning. Du kan skapa andra metoder i den här klassen efter behov och anropa dem från metoden ExecuteAsync. Klassnamnet måste vara Skript och scriptBase måste implementeras.

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

Definition av stödklasser och gränssnitt

Följande klasser och gränssnitt refereras av skriptklassen. De kan användas för lokala tester och sammanställningar.

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 Hej världen som svar på alla förfrågningar.

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 del text som matchar och regex-uttrycket och returnerar resultatet av matchningen 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;
}

Vidarebefordransskript

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:

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år du till Power Platform-anslutningsprogram i GitHub.

Vanliga frågor och svar om anpassad kod

För mer information om anpassad kod, gå till Steg 4: (tillval) Använd stöd för anpassad kod.

F: Går det att använda flera skript per anpassad anslutningsprogram?
A: Nej, det går bara att ha en skriptfil per anpassad anslutning.

F: Ett internt serverfel visas när min anpassade anslutning uppdateras. Vad kan vara problemet?
A: Troligtvis är detta ett problem när du kompilerar koden. I framtiden kommer vi att visa en fullständig lista med kompileringsfel för att förbättra den här upplevelsen. Vi rekommenderar att du använder stödklasser för att testa kompileringsfel lokalt för tillfället som en lösning.

F: Kan jag lägga till loggning i min kod och få ett spårningsspårning för felsökning?
A: Inte för närvarande, men stöd för detta kommer att läggas till i framtiden.

F: Hur testar jag koden under tiden?
A: Testa den lokalt och se till att du kan kompilera kod med enbart de namnutrymme som finns i namnutrymme som stöds. Information om lokala tester finns i Skriva kod i en anpassad anslutningsprogram.

F: Finns det några gränser?
S: Ja. Skriptet måste slutföras inom 5 sekunder och skriptfilens storlek får inte vara längre än 1 MB.

F: Kan jag skapa min egen http-klient i skriptkod?
A: För tillfället ja, men vi kommer att blockera det här i framtiden. Rekommenderad metod är this.Context.SendAsync.

F: Kan jag använda anpassad kod med lokal datagateway?
S: Inte för närvarande.

Support för Virtual Network

När anslutningsprogrammet används i en Power Platform-miljö länkad till ett Virtual Network gäller följande begränsningar:

  • Context.SendAsync använder en offentlig slutpunkt och kan därför inte komma åt data från privata slutpunkter som är synliga i Virtual Network.

Allmänna kända problem och begränsningar

OperationId-sidhuvudet kan returneras i base64-kodat format i vissa regioner. Om OperationIds värde krävs för en implementering ska det vara base64 avkodat för användning på ett sätt som liknar följande.

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 ett anpassat anslutningsprogram från grunden

Ge feedback

Vi uppskattar feedback på problem med vår plattform för anslutningsprogram eller förslag på nya funktioner. Om du vill lämna feedback går du till Skicka problem eller få hjälp med anslutningsprogram och väljer typ av feedback.