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 helemaal zelf 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 Script zijn en 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, ga naar Power Platform Connectors in GitHub.
Veelgestelde vragen over aangepaste code
Ga naar Stap 4: (Optioneel) Gebruik ondersteuning voor aangepaste code voor meer informatie over 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 zou het probleem kunnen zijn?
A: Hoogstwaarschijnlijk is dit een probleem met 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 voorlopig de ondersteunende klassen te gebruiken om compilatiefouten lokaal te testen als tijdelijke oplossing.
V: Kan ik logging aan mijn code toevoegen en een tracering krijgen voor foutopsporing?
A: Momenteel nog niet, maar ondersteuning hiervoor wordt in de toekomst toegevoegd.
V: Hoe kan ik in de tussentijd mijn code testen?
A: Test het lokaal en zorg ervoor dat u code alleen kunt compileren met behulp van de naamruimten die zijn opgegeven in de ondersteunde naamruimten. Ga naar Code schrijven in een aangepaste connector voor informatie over lokaal testen.
V: Zijn er grenzen?
A: Ja. Uw script moet binnen 2 minuten volledig zijn uitgevoerd en de grootte van uw scriptbestand mag niet groter zijn dan 1 MB. Deze nieuwe time-out van 2 minuten geldt voor alle nieuw aangemaakte aangepaste connectoren. Voor bestaande aangepaste connectoren moeten klanten de connector bijwerken om de nieuwe time-out toe te passen.
V: Kan ik mijn eigen http-client maken in scriptcode?
A: Op dit moment wel, maar in de toekomst blokkeren we dit. De aanbevolen manier is om deze.Context.SendAsync methode te gebruiken.
V: Kan ik aangepaste code gebruiken met de on-premises gegevensgateway?
A: Op dit moment niet, nee.
Virtual Network-ondersteuning
Wanneer de connector wordt gebruikt in een Power Platform omgeving die is gekoppeld aan een virtueel netwerk, gelden er beperkingen:
- 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
Maak een aangepaste connector vanaf nul
Feedback geven
We stellen feedback over problemen met ons connectorplatform of ideeën voor nieuwe functies zeer op prijs. Als u feedback wilt geven, gaat u naar Problemen melden of hulp krijgen met connectoren en selecteert u het type feedback.