[Power Apps]カスタムコネクタを開発してみた

## 背景

Power Appsで直接自作したAPIを呼び出したく、カスタムコネクタを作成してみました。カスタムコネクタはOpenAPI定義に対応しているため、Azure FunctionsでOpenAPI定義対応のFaaSを開発してみました。

## 前提条件

* Power Apps使用可能なライセンスがあること
* カスタムコネクタの作成権限があること
* Azure Functionsのリソース作成権限があること
* Azure FunctionsをVisual Studioを使用して開発すること
* Azure Functionsの開発言語はC#であること

## 開発手順

## Azure Functions準備

### 1. HTTPトリガーの関数を作成。

※パッケージ（`Microsoft.Azure.WebJobs.Extensions.OpenApi`）を導入する必要があるため、**インプロセスモデル**で関数を作成する。

> 分離ワーカーモデルとインプロセスモデルについては、
> [https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=python-v2%2Cisolated-process%2Cnodejs-v4%2Cfunctionsv2\&pivots=programming-language-csharp](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=python-v2%2Cisolated-process%2Cnodejs-v4%2Cfunctionsv2&pivots=programming-language-csharp) を参照。
> ※「Isolated」は分離ワーカーモデルを指します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/10fbff25-40bc-4722-a98d-37485962efe0.png)


### 2. 以下、例に従って実装する。

> 属性については、[https://tech-lab.sios.jp/archives/32091](https://tech-lab.sios.jp/archives/32091) を参照。

```csharp
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;

namespace FunctionApp1
{
    public static class Function1
    {
        [FunctionName("Function1")]
        [OpenApiOperation(operationId: "Run", tags: new[] { "name" })]
        [OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
        [OpenApiParameter(name: "name", In = ParameterLocation.Query, Required = true, Type = typeof(string), Description = "The **Name** parameter")]
        [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(FunctionResult), Description = "The OK response")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            string responseMessage = string.IsNullOrEmpty(name)
                ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                : $"Hello, {name}. This HTTP triggered function executed successfully.";

            return new OkObjectResult(new FunctionResult { Message = responseMessage });
        }
    }

    public class FunctionResult
    {
        public string Message { get; set; }
    }
}
```

### 3. ローカルデバッグして、動作確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/fb0257db-a263-48c5-b80c-adf826bc510e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/b965228e-5cc9-4f12-b9d5-0833409a2cd2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/b5db0d32-d742-44fa-b4df-21c11a4258ca.png)


### 4. OpenAPIファイルの取得

ローカルデバッグして、URL（`http://localhost:7071/api/swagger.json`）をHTTPリクエストして、Power Appsのカスタムコネクタでインポートする設定ファイルを取得する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/dfa2f39d-82ff-4d01-95ed-3912bcdf1e7b.png)

### 5. Azure Functionsのリソースを作成

### 6. 手順2で作成したソースを、Azureに作成したFunctionsリソースへデプロイする。

> 詳細手順:
> [https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-create-function-app-portal?pivots=programming-language-csharp](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-create-function-app-portal?pivots=programming-language-csharp)

## Power Apps準備

### 1. カスタムコネクタ作成画面にて「OpenAPIファイルをインポートします」を選択し、先ほど取得したファイルをインポートする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/4847b7c7-f03b-4a7b-bea2-adb29af4b8b8.png)

### 2. 「全般」のホストが `localhost` になっているため、実際にデプロイした Azure Functions のホスト名に変更する。

### 3. 「6.テスト」で「新しい接続」を押下し、関数キーを入力して接続テストを行う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/c7e2faf8-a3c6-4cc3-af8f-13ea39741764.png)

### 4.  Power Apps キャンバスアプリで「データの追加」から作成したカスタムコネクタに接続し、Power Appsに実装する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/96931fef-1b51-4eab-8ece-961856f59c9e.png)

## まとめ

いかがだったでしょうか。

長らくカスタムコネクタを作っていなかったため、ある機会があって、開発しようとしたとき、忘れておりました。日々、投稿して見返すことができるようにしていこうｔ思います。

この記事が役に立った、または興味ある方がいらっしゃいましたら、「コメント・いいね」いただけると幸いです。

---