사용자 지정 코드는 기존 정책 템플릿의 범위를 넘어 요청 및 응답 페이로드를 변환합니다. 코드를 사용하는 경우 코드 없는 정의보다 우선합니다.
자세한 내용은 처음부터 사용자 지정 커넥터 만들기를 참조하세요.
스크립트 클래스
코드는 런타임 중에 실행되는 메서드 ExecuteAsync를 구현해야 합니다. 필요에 따라 이 클래스에 다른 메서드를 추가로 만들고 ExecuteAsync 메서드에서 해당 메서드들을 호출할 수 있습니다. 클래스 이름이어야 Script 하며 구현 ScriptBase해야 합니다.
public class Script : ScriptBase
{
public override Task<HttpResponseMessage> ExecuteAsync()
{
// Your code here
}
}
지원 클래스 및 인터페이스 정의
클래스는 Script 다음 클래스 및 인터페이스를 참조합니다. 로컬 테스트 및 컴파일에 사용합니다.
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);
}
샘플
헬로 월드 스크립트
이 샘플 스크립트는 항상 모든 요청에 대한 응답으로 헬로 월드 반환합니다.
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;
}
정규식 스크립트
다음 샘플에서는 일치시킬 일부 텍스트와 정규식을 사용하고 응답에서 일치의 결과를 반환합니다.
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# 네임스페이스가 지원되는 것은 아닙니다. 현재 다음 네임스페이스의 함수만 사용할 수 있습니다.
중요합니다
현재 지원되는 .NET 버전은 .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 샘플
DocuSign 커넥터의 예를 보려면 GitHub의 Power Platform 커넥터로 이동하십시오.
사용자 지정 코드 FAQ
사용자 지정 코드에 대한 자세한 내용은 4단계: (선택 사항) 사용자 지정 코드 지원 사용
Q: 사용자 지정 커넥터당 여러 스크립트를 사용할 수 있나요?A: 아니요, 사용자 지정 커넥터당 하나의 스크립트 파일만 사용할 수 있습니다.
Q: 사용자 지정 커넥터를 업데이트할 때 내부 서버 오류가 발생합니다. 무엇이 문제가 될 수 있습니까? A: 대부분의 경우 코드를 컴파일하는 데 문제가 있습니다. 나중에 시스템은 이 환경을 개선하기 위해 컴파일 오류의 전체 목록을 표시합니다. 지금은 지원 클래스를 사용하여 컴파일 오류를 로컬로 테스트하여 해결 방법으로 사용합니다.
Q: 내 코드에 로깅을 추가하고 디버깅에 대한 추적을 가져올 수 있나요?A: 현재는 아니지만 이 기능에 대한 지원은 나중에 추가될 예정입니다.
Q: 그 동안 내 코드를 테스트하려면 어떻게 해야 하나요?A: 로컬로 테스트하고 지원되는 네임스페이스에 제공된 네임스페이스만 사용하여 코드를 컴파일할 수 있는지 확인합니다. 로컬 테스트에 대한 자세한 내용은 사용자 지정 커넥터의 코드 작성을 참조하세요.
Q: 제한이 있나요?A: 예. 스크립트는 2분 이내에 실행을 완료해야 하며 스크립트 파일의 크기는 1MB를 초과할 수 없습니다. 이 새로운 2분 시간 제한은 새로 만든 사용자 지정 커넥터에 적용됩니다. 기존 사용자 지정 커넥터의 경우 커넥터를 업데이트하여 새 시간 제한을 적용해야 합니다.
Q: 스크립트 코드에서 내 HTTP 클라이언트를 만들 수 있나요?A: 현재, 예, 하지만 시스템은 나중에이 기능을 차단합니다. 권장되는 방법은 this.Context.SendAsync 메서드를 사용하는 것입니다.
Q: 온-프레미스 데이터 게이트웨이에서 사용자 지정 코드를 사용할 수 있나요?A: 현재는 아닙니다.
Virtual Network 지원
가상 네트워크에 연결된 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
}
다음 단계:
피드백 제공
커넥터 플랫폼 문제 또는 새로운 기능 아이디어에 대한 피드백에 감사 드립니다. 피드백을 제공하려면 문제 제출 또는 커넥터 관련 도움말 보기로 이동하여 피드백 유형을 선택하십시오.