Azure Functionsで自作したカスタムコネクタをPower Automateで使おうとしたらハマった事象と原因と回避策について
随分とタイトルの示す範囲が大きくなりましたが、そういうことです。
やろうとしていたことは「Azure Functions
で作成した関数アプリをPower Automate
で使う」という至ってシンプルなものでした。
しかし、いざ実践してみると期待した通りに動作しなかったため、しばらく悩み続けてなんとか解消した話です。
事象
Azure Functions
で作成した関数アプリをカスタムコネクタを使って呼び出すようにしました。
新規にフローを作成してカスタムコネクタのアクションを実行すると失敗し、次のようなメッセージが表示されました。
ResponseSwaggerSchemaValidationFailure. API 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' が、種類 'OpenApiConnection' のワークフロー操作 '<API名>' について無効な応答を返しました。エラーの詳細: 'API 操作 '<API名>' では、プロパティ 'body' の種類を 'Object' にする必要がありますが、種類が 'String' です。'
内容的には json の応答を Object から String にしろと言うことのようです。
2020/11/16 追記 (コメント頂きましたので修正)
内容的にはカスタムコネクタでは Object が来る想定だったけど String が来たよ、ということのようです。
ちなみにAzure Functions
では、作成した関数の応答は json で返していました。
ただし、この現象が発生するのは実際のフローのみで、カスタムコネクタの[テスト]タブで実行した場合や、HTTP アクションで同じ URL 呼び出しを行っても同じ現象は発生しませんでした。
似たような事象が発生していないか Power Automate で探したところ、ドンピシャなスレッドがありました。が、質問した方はカスタムコネクタを修正して対応したようです。(良いのかな…)
原因
色々試した結果、原因はAzure Functions
側にあることがわかりました。
応答する際に json にシリアライズしたのは良いのですが、json 文字列を body に設定してしまっていました。
はい、つまり完全に私のしょーもないミスが原因ですね。
具体的には次のようなコードになっていました。
[FunctionName("function")] public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req, ILogger log) { ...省略 var json = Newtonsoft.Json.JsonConvert.SerializeObject(result, _settings); return new OkObjectResult(json); }
このまま関数を呼び出すと応答結果のContent-Type
は、text/plain
になってしまいます。
要はこれをapplication/json
にすれば良いわけですね。
対策
今回のケースでは応答は json で返し、シリアライズする際の書式設定はNewtonsoft.Json.JsonSerializerSettings
で設定していたため、Microsoft.AspNetCore.Mvc.JsonResult
で応答する手法を取りました。
この方法にたどり着くまでに twitter 上でしばてぃさん(@shibatea365)に何度もアドバイスいただきました。感謝の極みです😂
さて、変更後のコードはこのようになります。
[FunctionName("function")] public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req, ILogger log) { ...省略 return new JsonResult(response, _settings); }
なお、JsonResult
を使う場合はMicrosoft.AspNetCore.Mvc.NewtonsoftJsonパッケージを追加する必要があります。
また、csproj
ファイルに<FrameworkReference Include="Microsoft.AspNetCore.App" />
を追加しないと以下のような事象が発生するそうなのでご注意を。
MethodNotFound when trying to call JsonResult ctor with JsonSerializerSettings #1907
これを実行するとContent-Type
はapplication/json
になり、Power Autoamte のフローも成功します。
最後に
本当にしょうもなことが原因で何日もハマってしまいました…
Azure Functions
についてはまだまだ初学者であったとは言え、今回のような事象はユニットテストでレスポンス ヘッダーまでテストして入れば検知できたはずです(やってませんでした!)。
ちょっと手を抜いた結果がこれです。
手を抜くの絶対ダメ!!!