Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Il codice personalizzato trasforma i payload di richieste e risposte oltre l'ambito di modelli di criteri esistenti. Quando si usa il codice, ha la precedenza sulla definizione senza codice.
Per altre informazioni consultare Creare un connettore personalizzato da zero.
Classe di script
Il codice deve implementare un metodo denominato ExecuteAsync, che viene eseguito durante il runtime. È possibile creare altri metodi in questa classe in base alle esigenze e chiamarli dal ExecuteAsync metodo . Il nome della classe deve essere Script e deve implementare ScriptBase.
public class Script : ScriptBase
{
public override Task<HttpResponseMessage> ExecuteAsync()
{
// Your code here
}
}
Definizione di classi e interfacce di supporto
La Script classe fa riferimento alle classi e alle interfacce seguenti. Usarli per il test e la compilazione locali.
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);
}
Esempi
Script Hello World
Questo script di esempio restituisce sempre Hello World come risposta per tutte le richieste.
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;
}
Script Regex
L'esempio seguente accetta un testo su cui effettuare la corrispondenza e l'espressione regex e restituisce il risultato della corrispondenza nella risposta restituita.
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;
}
Script di inoltro
L'esempio seguente inoltra la richiesta in ingresso al 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;
}
Script di inoltro e di trasformazione
L'esempio seguente inoltra la richiesta in ingresso e trasforma la risposta restituita dal 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 == "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;
}
Namespace supportati
Non tutti i namespace C# sono supportati. Attualmente, puoi utilizzare soltanto le funzioni appartenenti ai seguenti namespace.
Importante
La versione .NET attualmente supportata è .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;
Esempi di GitHub
Per esempi del connettore DocuSign, visita Power Platform Connectors su GitHub.
Domande frequenti sul codice personalizzato
Per altre informazioni sul codice personalizzato, vedere Passaggio 4: (Facoltativo) Usare il supporto del codice personalizzato.
D: È possibile usare più script per ogni connettore personalizzato?R: No, è possibile usare un solo file di script per ogni connettore personalizzato.
D: Viene visualizzato un errore interno del server durante l'aggiornamento del connettore personalizzato. Quale potrebbe essere il problema? R: Molto probabilmente si verifica un problema durante la compilazione del codice. In futuro, il sistema visualizza l'elenco completo degli errori di compilazione per migliorare questa esperienza. Per il momento, usare le classi di supporto per testare gli errori di compilazione in locale come soluzione alternativa.
D: È possibile aggiungere la registrazione al codice e ottenere una traccia per il debug?R: Non attualmente, ma il supporto per questa funzionalità verrà aggiunto in futuro.
D: Come è possibile testare il codice nel frattempo?R: Testarlo in locale e assicurarsi di poter compilare il codice usando solo gli spazi dei nomi forniti negli spazi dei nomi supportati. Per informazioni sui test locali, vedere Scrivere codice in un connettore personalizzato.
D: Esistono limiti?R: Sì. L'esecuzione dello script deve terminare nel giro di 2 minuti e le dimensioni del file di script non possono essere superiori a 1 MB. Questo nuovo timeout di 2 minuti si applica a tutti i connettori personalizzati appena creati. Per i connettori personalizzati esistenti, è necessario aggiornare il connettore per applicare il nuovo timeout.
D: È possibile creare un client HTTP personalizzato nel codice script?R: Attualmente, sì, ma il sistema blocca questa funzionalità in futuro. Il modo consigliato è usare il metodo this.Context.SendAsync.
D: È possibile usare codice personalizzato con il gateway dati locale?R: Non al momento, no.
Supporto di Rete virtuale
Quando si usa il connettore in un ambiente Power Platform collegato a una rete virtuale, si applicano le limitazioni seguenti:
-
Context.SendAsyncusa un endpoint pubblico, in modo che non possa accedere ai dati da endpoint privati nella rete virtuale.
Problemi noti e limitazioni generali
In alcune aree l'intestazione OperationId restituisce in formato con codifica Base64. Se l'implementazione richiede il valore OperationId, decodificalo da base64 per utilizzarlo.
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
}
Passaggio successivo
Creare un connettore personalizzato da zero.
Fornire commenti
L'invio da parte degli utenti di feedback sui problemi riscontrati con la piattaforma di connettori o di idee su nuove funzionalità è molto apprezzato. Per fornire un feedback, vai a Inviare problemi o ottenere assistenza per i connettori e seleziona il tipo di commenti.