Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Benutzerdefinierter Code transformiert Anforderungs- und Antwortnutzlasten über den Umfang vorhandener Richtlinienvorlagen hinaus. Wenn Sie Code verwenden, hat sie Vorrang vor der codelosen Definition.
Weitere Informationen finden Sie unter Einen angepassten Konnektor von Grund auf neu erstellen
Skriptklasse
Ihr Code muss eine Methode namens ExecuteAsync implementieren, die zur Laufzeit ausgeführt wird. Sie können bei Bedarf andere Methoden in dieser Klasse erstellen und sie aus der ExecuteAsync Methode aufrufen. Der Klassenname muss Script sein, und er muss ScriptBase implementieren.
public class Script : ScriptBase
{
public override Task<HttpResponseMessage> ExecuteAsync()
{
// Your code here
}
}
Definition unterstützender Klassen und Schnittstellen
Die Script Klasse verweist auf die folgenden Klassen und Schnittstellen. Verwenden Sie sie für lokale Tests und Kompilierung.
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);
}
Beispiele
„Hallo Welt“-Skript
Dieses Beispielskript gibt immer Hallo Welt als Antwort für alle Anforderungen zurück.
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
Das folgende Beispiel verwendet einen abzugleichenden Text und den regulären Ausdruck und gibt das Ergebnis der Übereinstimmung in der Antwort zurück.
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;
}
Weiterleitungsskript
Das folgende Beispiel leitet die eingehende Anforderung an das Back-End weiter.
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;
}
Weiterleitungs- und Transformationsskript
Das folgende Beispiel leitet die eingehende Anforderung weiter und wandelt die vom Back-End zurückgegebene Antwort um.
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;
}
Unterstützte Namespaces
Nicht alle C#-Namespaces werden unterstützt. Derzeit können Sie nur Funktionen aus den folgenden Namespaces verwenden.
Von Bedeutung
Die derzeit unterstützte .NET Version ist .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-Beispiele
Beispiele im DocuSign-Connector finden Sie unter Power Platform-Connectors auf GitHub.
Häufig gestellte Fragen zu benutzerdefiniertem Code
Weitere Informationen zu benutzerdefiniertem Code finden Sie unter Schritt 4: (Optional) Verwenden der Unterstützung von benutzerdefiniertem Code.
F: Kann ich mehrere Skripts pro benutzerdefiniertem Connector verwenden?A: Nein, Sie können pro benutzerdefiniertem Connector nur eine Skriptdatei verwenden.
F: Beim Aktualisieren meines benutzerdefinierten Connectors wird ein interner Serverfehler angezeigt. Was könnte das Problem sein? A: Wahrscheinlich gibt es ein Problem beim Kompilieren ihres Codes. In Zukunft zeigt das System die vollständige Liste der Kompilierungsfehler an, um diese Erfahrung zu verbessern. Verwenden Sie nun die unterstützenden Klassen , um Kompilierungsfehler lokal als Problemumgehung zu testen.
F: Kann ich meinem Code Protokollierung hinzufügen und einen Trace zum Debuggen erhalten?A: Derzeit nicht, aber diese Funktion wird künftig unterstützt.
F: Wie kann ich meinen Code in der Zwischenzeit testen?A: Testen Sie ihn lokal, und stellen Sie sicher, dass Sie Code kompilieren können, indem Sie nur die namespaces verwenden, die in unterstützten Namespaces bereitgestellt werden. Informationen zu lokalen Tests finden Sie unter Schreiben von Code in einem benutzerdefinierten Connector.
F: Gibt es Beschränkungen?A: Ja. Die Ausführung Ihres Skripts muss innerhalb von 2 Minuten abgeschlossen sein und die Größe Ihrer Skriptdatei darf 1 MB nicht überschreiten. Dieses neue 2-Minuten-Timeout gilt für alle neu erstellten benutzerdefinierten Connectors. Für vorhandene benutzerdefinierte Konnektoren müssen Sie den Konnektor aktualisieren, damit das neue Timeout wirksam wird.
F: Kann ich meinen eigenen HTTP-Client im Skriptcode erstellen?A: Derzeit ja, aber das System blockiert dieses Feature in Zukunft. Die empfohlene Vorgehensweise ist die Verwendung der Methode this.Context.SendAsync.
F: Kann ich benutzerdefinierten Code mit dem lokalen Datengateway verwenden?A: Zurzeit nicht, nein.
Unterstützung von Virtual Network
Wenn Sie den Connector in einer Power Platform-Umgebung verwenden, die mit einem virtuellen Netzwerk verknüpft ist, gelten die folgenden Einschränkungen:
-
Context.SendAsyncverwendet einen öffentlichen Endpunkt, sodass er nicht auf Daten von privaten Endpunkten im virtuellen Netzwerk zugreifen kann.
Allgemeine bekannte Probleme und Einschränkungen
In einigen Regionen gibt der OperationId Header im base64-codierten Format zurück. Wenn die Implementierung den OperationId Wert erfordert, decodiert base64 ihn für die Verwendung.
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
}
Nächster Schritt
Erstellen Sie einen benutzerdefinierten Konnektor von Grund auf neu
Feedback senden
Wir freuen uns sehr über Feedback zu Problemen mit unserer Connector-Plattform oder neuen Feature-Ideen. Wenn Sie Feedback geben möchten, wechseln Sie zu Probleme melden oder Hilfe zu Connectors erhalten und wählen Sie den Typ Ihres Feedbacks aus.