练习 - 使用自定义代码

已完成

在本练习中,您要向现有自定义连接器添加新操作。 然后,您将使用自定义代码来实施该操作并转换响应。

您将修改具有 ListInvoice 操作但没有 LastInvoice 操作的 Contoso Invoicing 自定义连接器。 为此,您需要添加 LastInvoice 操作以检索创建的最新发票。 Contoso Invoicing 的网络 API 不支持此操作,因此您应使用在 LastInvoice 操作上运行的自定义代码将请求重定向到 API 上的 ListInvoice,然后将响应转换为仅返回创建的最后一张发票。

重要提示

使用已预配 Microsoft Dataverse 的测试环境。 如果您还没有此类环境,请转至 Microsoft Power Apps 开发人员计划,注册加入开发人员计划。

任务:准备环境

在本任务中,您需要将解决方案导入环境中。

  1. 转到 Microsoft Power Automate 并确保您处于正确的环境中。

  2. 在左侧导航窗格中,选择数据 > 自定义连接器

  3. 确认您的环境中是否已具有 Contoso Invoicing 自定义连接器。

    显示自定义连接器的屏幕截图。

  4. 如果您的环境中已具有 Contoso Invoicing 自定义连接器,请跳到本练习中的下一个任务。 如果没有自定义连接器,请继续执行第 5 步。

  5. 选择解决方案 > 导入

  6. 选择浏览

  7. 选择资源文件夹中的 ContosoInvoicingExtensions_1_0_0_0.zip 解决方案,然后选择打开

  8. 选择下一步

  9. 选择导入,然后等待导入完成。 您应在导入完成后收到成功消息。

  10. 选择发布所有自定义并等待发布完成。 请勿导航离开本页面。

任务:创建 LastInvoice 操作

在本任务中,您将在 Contoso Invoicing 自定义连接器中创建一项新操作。

  1. 选择您导入的 Contoso Invoicing - Extensions 解决方案。 此时应显示 Contoso Invoicing - Extensions 自定义连接器组件。

  2. 选择 Contoso Invoicing - Extensions 连接器,然后选择编辑。 如果您的连接器是在其他练习中创建的,则其名称中可能不含 Extensions,这没有关系。

    “编辑”解决方案按钮的屏幕截图。

  3. 选择定义选项卡,然后选择 + 新建操作

    显示创建新操作按钮的屏幕截图。

  4. 转到请求部分并选择 + 从示例导入

    显示“从示例导入”按钮的屏幕截图。

  5. 动词部分中选择 Get,将 https://contosoinvoicingtest.azurewebsites.net/GetLastInvoice 粘贴到 URL 框中,然后选择导入

    显示“从示例导入”对话框中的请求的屏幕截图。

  6. 向下滚动到响应部分并选择 + 添加默认响应

    显示“添加默认响应”按钮的屏幕截图。

  7. 正文字段中粘贴以下 JSON,然后选择导入

    {
      "invoiceId": "1934",
      "date": "2023-03-19T06:55:45.9039452+00:00",
      "createDate": "2023-03-14T06:55:45.9039456Z",
      "amount": 8000,
      "accountId": "1001",
      "accountName": "Wing Tips",
      "status": "Invoiced",
      "typeId": 1,
      "purchaseOrderId": "3004",
      "tags": "New Account;Special Pricing;Non-returnable"
    }
    
  8. 选择测试选项卡并选择更新连接器,然后等待更新完成。

    显示“更新连接器”按钮的屏幕截图。

  9. 启动新的浏览器窗口或选项卡,然后转到 Contoso Invoicing

  10. 选择 API 密钥链接。

  11. 复制 API 密钥

  12. 将此密钥保存在记事本中。

  13. 返回连接器,选择测试选项卡,然后选择 + 新建连接

    添加新连接按钮的屏幕截图。

  14. API 密钥字段中粘贴复制的密钥,然后选择创建连接

  15. 选择刷新连接

  16. 向下滚动到操作部分,选择 GetLastInvoice,然后选择测试操作

    “测试”操作按钮的屏幕截图。

    您应该会收到 404 错误,因为该 API 没有 GetLastInvoice 操作。

    显示操作失败的屏幕截图。

    请勿导航离开本页面。

任务:为连接器添加代码

在本任务中,您将添加用于执行 GetLastInvoice 操作的代码。

  1. 选择代码选项卡,然后打开已启用代码切换开关。

    显示启用代码切换按钮的屏幕截图。

  2. 选择操作下拉菜单,然后选择 GetLastInvoice 操作。

    显示所选操作的屏幕截图。

  3. 代码字段中粘贴以下代码,然后选择测试选项卡。

    public class Script : ScriptBase
    {
        public override async Task<HttpResponseMessage> ExecuteAsync()
        {
            // Check if the operation ID matches what is specified in the OpenAPI definition of the connector
            if (String.Equals(this.Context.OperationId, "GetLastInvoice", StringComparison.OrdinalIgnoreCase))
            {
                this.Context.Request.RequestUri = ReplaceUri(this.Context.Request.RequestUri, "GetLastInvoice", "ListInvoices");
                return await this.HandleGetLastInvoiceOperation().ConfigureAwait(false);
            }
            else
            {
                //pass-thru any other operation to the API directly
                return await this.HandleForwardOperation().ConfigureAwait(false);
            }
        }
        private Uri ReplaceUri(Uri original, string fromValue, string toValue)
        {
            try
            {
                var builder = new UriBuilder(original.ToString().Replace(fromValue, toValue));
                return builder.Uri;
            }
            catch (Exception ex)
            {
                throw new Exception(original.ToString().Replace(fromValue, toValue));
            }
        }
        private async Task<HttpResponseMessage> HandleGetLastInvoiceOperation()
        {
            JObject newResult = null;
            // Use the context to 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)
            {
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    var responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false);
                    var result = JObject.Parse(responseString);
                    // Wrap the original JSON object into a new JSON object with just two properties
                    if (result != null && result.ContainsKey("invoices") && result["invoices"].HasValues)
                    {
                        var sortedArray = result["invoices"].OrderBy(jo => (DateTime)jo["date"]).ToArray();
                        var lastInvoice = sortedArray[0];
                        newResult = new JObject
                        {
                            ["invoiceid"]   = lastInvoice["invoiceid"],
                            ["date"]        = lastInvoice["date"],
                            ["createDate"]  = lastInvoice["createDate"],
                            ["amount"]      = lastInvoice["amount"],
                            ["accountId"]   = lastInvoice["accountId"],
                            ["accountName"] = lastInvoice["accountName"],
                            ["status"]      = lastInvoice["status"],
                            ["typeId"]      = lastInvoice["typeId"],
                            ["purchaseOrderId"] = lastInvoice["purchaseOrderId"],
                            ["tags"]        = lastInvoice["tags"]
    
                        };
                    }
                    else
                    {
                        newResult = new JObject
                        {
                            ["invoiceid"] = "-9999",
                            ["status"] = "No Invoices",
                        };
                    }
                }
                else
                {
                    newResult = new JObject
                        {
                            ["invoiceid"] = "-9999",
                            ["status"] = "Error retrieving invoices",
                        };
                }
                response.Content = CreateJsonContent(newResult.ToString());
                response.StatusCode = HttpStatusCode.OK;
            }
            return response;
        }
        private async Task<HttpResponseMessage> HandleForwardOperation()
        {
            // 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;
        }
    }
    

    显示代码和“测试”选项卡的屏幕截图。

  4. 审查代码。 代码应包含以下逻辑:

    • 检查是否为 GetLastInvoice 操作,如果不是,则将未修改的请求转发到网络 API

    • 更改请求以使用网络 API 上的 ListInvoice 操作

    • 使用 SendAsync 调用网络 API

    • 将响应转换为仅包含单个发票对象(即最近创建的发票)

  5. 选择测试选项卡并选择更新连接器,然后等待更新完成。

  6. 向下滚动到操作部分,选择 GetLastInvoice,然后选择测试操作

    “测试操作”操作的屏幕截图。

您将收到显示最后一张发票的响应。

显示操作响应的屏幕截图。