Delen via


Code in een aangepaste connector schrijven

Aangepaste code transformeert payloads voor aanvragen en antwoorden buiten het bereik van bestaande beleidssjablonen. Wanneer er code wordt gebruikt, heeft deze voorrang op de codeloze definitie.

Ga voor meer informatie naar Een aangepaste connector maken.

Script-klasse

Uw code moet een methode implementeren met de naam ExecuteAsync, die tijdens runtime wordt aangeroepen. U kunt indien nodig andere methoden in deze klasse maken en deze aanroepen vanuit de methode ExecuteAsync. De klassenaam moet zijn Script en deze moet ScriptBase implementeren.

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

Definitie van ondersteunende klassen en interfaces

Naar de volgende klassen en interfaces wordt verwezen door de Script-klasse. Deze kunnen worden gebruikt voor lokaal testen en compileren.

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);
}

Voorbeelden

Hallo Wereld-script

Dit voorbeeldscript retourneert altijd Hallo Wereld als antwoord voor alle verzoeken.

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-script

In het volgende voorbeeld is wat tekst nodig om te vergelijken en de regex-expressie en wordt het resultaat van de overeenkomst in de respons geretourneerd.

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;
}

Doorstuurscript

In het volgende voorbeeld wordt de binnenkomende aanvraag doorgestuurd naar de back-end.

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;
}

Doorsturen en transformeren-script

In het volgende voorbeeld wordt de binnenkomende aanvraag doorgestuurd en wordt de respons van de back-end getransformeerd.

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;
}

Ondersteunde naamruimten

Niet alle C#-naamruimten worden ondersteund. Momenteel kunt u alleen functies uit de volgende naamruimten gebruiken.

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-voorbeelden

Voor voorbeelden in de DocuSign-connector gaat u naar Power Platform-connectors in GitHub.

Veelgestelde vragen over aangepaste code

Ga voor meer informatie over aangepaste code naar Stap 4: (Optioneel) gebruik van ondersteuning voor aangepaste code.

V: Is het mogelijk om meerdere scripts per aangepaste connector te gebruiken?
A: Nee, er wordt slechts één scriptbestand per aangepaste connector ondersteund.

V: Ik krijg een interne serverfout bij het updaten van mijn aangepaste connector. Wat kan het probleem zijn?
A: Hoogstwaarschijnlijk is dit een probleem bij het compileren van uw code. In de toekomst geven we de volledige lijst met compilatiefouten weer om deze ervaring te verbeteren. We raden aan om de ondersteunende klassen te gebruiken om compilatiefouten voorlopig lokaal te testen als een tijdelijke oplossing.

V: Kan ik logboekregistratie aan mijn code toevoegen en een trace voor foutopsporing krijgen?
A: Momenteel niet, maar ondersteuning hiervoor zal in de toekomst worden toegevoegd.

V: Hoe kan ik in de tussentijd mijn code testen?
A: Test de code lokaal en zorg ervoor dat u code kunt compileren met alleen de naamruimten die in ondersteunde naamruimten is vermeld. Ga voor informatie over lokaal testen naar Code schrijven in een aangepaste connector.

V: Zijn er limieten?
A: Ja. Uw script moet binnen 5 seconden worden uitgevoerd en uw scriptbestand mag niet groter zijn dan 1 MB.

V: Kan ik mijn eigen http-client in scriptcode maken?
A: Momenteel wel, maar we zullen dit in de toekomst blokkeren. De aanbevolen manier is om de this.Context.SendAsync-methode te gebruiken.

V: Kan ik aangepaste code gebruiken met de on-premises gegevensgateway?
A: Momenteel niet.

Virtual Network-ondersteuning

Wanneer de connector wordt gebruikt in een Power Platform-omgeving die is gekoppeld aan een Virtual Network, zijn er beperkingen van toepassing:

  • Context.SendAsync maakt gebruik van een openbaar eindpunt en heeft daarom geen toegang tot gegevens van privé-eindpunten die beschikbaar zijn in het Virtual Network.

Algemene bekende problemen en beperkingen

De OperationId-header kan in bepaalde regio's worden geretourneerd in een base64-gecodeerde indeling. Als de waarde van OperationId is vereist voor een implementatie, moet deze voor gebruik met base64 worden gedecodeerd op een wijze die vergelijkbaar is met de volgende.

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
}

Volgende stap

Een volledig nieuwe aangepaste connector maken

Feedback geven

We stellen feedback over problemen met ons connectorplatform of ideeën voor nieuwe functies zeer op prijs. Om feedback te geven, gaat u naar Problemen melden of hulp krijgen met connectoren en selecteer uw feedbacktype.