在自訂連接器中撰寫程式碼
自訂程式碼會轉換超出現有原則範本範圍的要求和回覆裝載。 使用程式碼時,其優先順序會比無程式碼定義高。
有關更多資訊,請轉到 從頭開始創建自定義連接器。
指令碼類別
您的程式碼必須執行名為 ExecuteAsync 的方法,其會在執行階段呼叫。 您可以視需要在此類別中建立其他方法,並從 ExecuteAsync 方法呼叫它們。 類名必須是 Script ,並且必須實現 ScriptBase。
public class Script : ScriptBase
{
public override Task<HttpResponseMessage> ExecuteAsync()
{
// Your code here
}
}
支援類別和介面的定義
下列類別和介面是由指令碼類別所參考。 它們可用於進行本機測試和編譯。
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);
}
範例
Hello World 指令碼
此範例指令碼會一律傳回 Hello World 做為對所有要求的回覆。
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 指令碼
以下範例將採用一些要比對的文字和 Regex 運算式,並在回覆中傳回相符結果。
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;
}
轉送指令碼
下列範例將傳入要求轉送到後端。
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;
}
轉送和轉換指令碼
下列範例會轉送傳入要求,並轉換從後端傳回的回覆。
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;
}
支援的命名空間
並非所有 C# 命名空間都有支援。 目前,您只能從以下命名空間使用函數。
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 範例
有關連接器中的 DocuSign 範例,請轉到 Power Platform GitHub 中的連接器 。
自訂程式碼常見問題集
要瞭解有關自定義代碼的更多資訊,請轉到 第 4 步:(可選)使用自定義代碼支援。
問:是否可以為每個自定義連接器使用多個腳本?
答: 不可以,每個自定義連接器僅支援一個腳本檔。
問:我在更新自定義連接器時收到內部伺服器錯誤。 可能是什麼問題?
A: 很可能是編譯代碼時出現的問題。 在未來,我們將顯示編譯錯誤的完整清單,以改善此體驗。 我們建議暫時使用 支援類 在本地測試編譯錯誤作為解決方法。
問:是否可以將日誌記錄添加到代碼中並獲取用於調試的跟蹤?
A: 目前沒有,但將來會添加對此的支援。
問:在此期間如何測試我的代碼?
A: 在本地測試它,並確保您可以僅使用支援的命名空間 中提供的命名空間來編譯代碼。 有關本地測試的資訊,請轉到 在自定義連接器中編寫代碼。
Q:是否有任何限制?
A: 可以。 您的腳本必須在 2 分鐘內完成執行,並且腳本檔的大小不能超過 1 MB。 這個新的 2 分鐘超時適用於任何新創建的自訂連接器。 對於現有的自定義連接器,客戶需要更新連接器以應用新的超時。
問:我是否可以在腳本代碼中創建自己的 HTTP 用戶端?
A: 目前可以,但我們將來會阻止此功能。 推薦的方法是使用 它。Context.SendAsync 方法。
問:是否可以將自定義代碼與本地數據閘道一起使用?
A: 目前沒有。
虛擬網路支援
在 Power Platform 連結到虛擬網路的環境中使用連接器時,存在限制:
- Context.SendAsync 使用公共端點,因此它無法存取虛擬網路上公開的私人端點中的資料。
一般已知問題與限制
OperationId 標頭在某些地區可能會以 base64 編碼格式傳回。 如果執行需要 OperationId 的值,應該是以類似下方的方式,解碼 base64 以供使用。
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
}
下一步
提供意見反應
非常感謝您提供有關連接器平台問題,或新功能構想的意見反應。 若要提供反饋,請轉到 提交問題或獲取有關連接器 的説明,然後選擇您的反饋類型。