😎

PowerApps から Azure Functions を使うメモ

5 min read

色々な方法があると思いますが、基本的には OpenAPI の定義を生成させてカスタムコネクタとして取り込んで PowerApps から呼ぶという流れになります。
動画による解説は、以下の YouTube 動画を見てください。ここでは作業メモを書いています。

https://www.youtube.com/watch?v=zpaaJPA6YIw

Azure Functions で OpenAPI に対応するには以下の拡張機能を使います。といっても Visual Studio から関数を作成するときに Http trigger with OpenAPI というひな型があるので、それをベースにして変えたい部分だけ変えるのが良いと思います。

https://github.com/Azure/azure-functions-openapi-extension

注意点は、まだ OpenAPI の拡張機能が preview というところですね。Preview が取れるのが待ち遠しいです。preview を含まないものでやるなら OpenAPI の定義は自作するか、Azure API Management とかで作ってもらうか Postman から生成するかなどなどいくつか方法があるので、そちらでやるのが良いと思います。

そして、PowerApps 側というか Power Platform では OpenAPI の定義からカスタムコネクターを作ることで外部の Web API を呼ぶことが出来ます。

https://docs.microsoft.com/ja-jp/connectors/custom-connectors/define-openapi-definition

これを使ってやってみましょう。

やったことのメモ

ということでカスタムコネクターは戻り値が JSON オブジェクトじゃないと取り込めないので、Http trigger with OpenAPI でデフォルトで生成されたものをすこし変えてレスポンスを文字列から JSON のオブジェクトになるように変更しました。コードとしては以下のような感じ。

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("Function2")]
        [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; }
    }
}

本格的にやるなら多分 Azure AD 認証で保護することになるんでしょうが、今回は一番お手軽な API Key による認証でいきます。後で時間があったら以下のドキュメントを見ながら Azure AD 認証も試したい…

https://docs.microsoft.com/ja-jp/connectors/custom-connectors/create-custom-connector-aad-protected-azure-functions

ローカルでデバッグ実行をしたら ngrok を使って外部からアクセス可能にします。コマンドとしてはこんな感じ。

ngrok http 7071 --host-header localhost

この状態では API Key による認証も何もない無防備状態の関数が公開されてしまうので重要なデータとか返すような関数ではしないでね。というかクラウドにデプロイするのがめんどくさくて ngrok 使ったので実際には Azure にデプロイした関数でやりましょう。

インターネットから関数が叩ける状態になったので、make.powerapps.con からカスタムコネクターを作ります。

ここら辺の手順は最初にも URL をはった以下のドキュメント通りです。

https://docs.microsoft.com/ja-jp/connectors/custom-connectors/define-openapi-definition

作った関数の OpenAPI の定義をゲットするには http://localhost:7071/api/swagger.yml にアクセスすると以下のように取得できるのでゲットして保存しておきましょう。

あとは、カスタムコネクタの取り込み時にホスト名の部分が localhost になっているので、そこだけ ngrok で生成された URL にします。

カスタムコネクターとして保存が出来たら、PowerApps で適当にキャンバスアプリを作って追加したコネクターを使いましょう。今回はローカルで実行している関数なので、カスタムコネクター用の接続作成時に入れる API Key は何でも素通りなので適当に作りました。本番では Azure ポータルから取れるキーにしましょう。

複数の関数がある場合はホストキーレベルの API Key を使っておかないと 1 つの関数しか呼べないと思うので気を付けましょう。

https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=csharp#authorization-scopes-function-level

後はボタンクリックなどの処理で適当に呼び出して完成です。

動きました。

ということで、気になってた PowerApps から自作の Web API を呼び出す方法を通してでやってみたので忘れないようにメモ書き完了!

結構簡単なので、興味のある人はこの記事にはってあるドキュメントを見ながら試してみてください。Power Platform のカスタムコネクタがプレミアムじゃないと使えないところが多分一番ネックになると思いますが試用版もあるので、それを使うのが良いと思います。