Visual Studio 2017 の Functions 対応
Visual Studio 2017では、バージョン15.3よりようやくAzure Functions の開発に対応しました。
今回はその導入方法と開発の流れを簡単にまとめます。
準備
Visual Studio 2017(15.3以降)をインストール
エディションはどれでも構いません(今回はCommunityエディションを使いました)。
インストール方法は割愛しますが、Azureと連携するので「Azureの開発」ワークロードを選択することが必須となります。
(あとからでもVisual Studio Installerの「変更」から追加可能です)
15.3以降では、Azure Functionsのテンプレートが選べるようになる…と思ったのですが、個別にアップデートが必要でした。
そうすると、無事にFunctionsのテンプレートが選べるようになりました。
開発
コードを書く
今回はC#でコードを書いていきます。
Azure FunctionsでC#を使う場合、いままでは「.csx」という拡張子のスクリプトでプログラムを書いていましたが、Visual Studio上でFunctionsの関数を作成することで、通常の「.cs」を使うことができ、普段のC#開発の感覚で関数をつくることができます。
※Azureのポータルから関数を作成した際は、「run.csx」の編集画面になるようです。
※C#スクリプト「.csx」の仕組みについては下記のドキュメントを参照
Azure Functions C# スクリプト開発者向けリファレンス
まずはVisual Studio 2017より、Azure Functionsのプロジェクトを作成します。
メニューからファイル→新規作成→プロジェクトと選択し、Visual C#のCloudを選択すると「Azure Functions」が出てくるので、これを選択してプロジェクトを作成します。
プロジェクトが出来上がったら、Functionsの処理を記述するためのcsファイルを作成します。
プロジェクトを右クリックし、追加→新しい項目と選択し、「Azure Functions」を選びます。
今回はWebhookの関数を作るので、「Generic Webhook」を選択します。
すると、以下のようなコードが書かれたファイルが作られます。
using System.Net;
using Newtonsoft.Json;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
namespace FunctionApp1
{
public static class Function1
{
[FunctionName("Function1")]
public static async Task<object> Run([HttpTrigger(WebHookType = "genericJson")]HttpRequestMessage req, TraceWriter log)
{
log.Info($"Webhook was triggered!");
string jsonContent = await req.Content.ReadAsStringAsync();
dynamic data = JsonConvert.DeserializeObject(jsonContent);
if (data.first == null || data.last == null)
{
return req.CreateResponse(HttpStatusCode.BadRequest, new
{
error = "Please pass first/last properties in the input object"
});
}
return req.CreateResponse(HttpStatusCode.OK, new
{
greeting = $"Hello {data.first} {data.last}!"
});
}
}
}
Webhookでよく使う、JSONのライブラリなどが最初からusingに書かれていて、いい感じです。
パッケージ自体もSDKに最初から含まれています。このあたり、「.csx」をAzure上で書く方法をとると結構面倒なので、このようなお膳立てをしてくれるのはとてもうれしいです。
この最初に生成されたコードは、「first」「last」というキーのデータ(ファーストネームとラストネームのことでしょう)をもつJSONを受け取って、その名前に挨拶する文字列を含むレスポンスを返す、という関数になっています。
JSONをdynamicで受け取ってそれを処理する、という処理はそのまま流用できそうなので、参考になりますね。
その他async/awaitなどを見ても、C#らしく簡潔なコードとなっていて、これによってもAzure Functionsの手軽さが際立ちます。
ローカルでデバッグする
では、このコードをローカルで実行・デバッグしてみたいと思います。
これも通常のVisual Studioでの開発と同じく、実行(デバッグの開始)ボタンを押すだけ。
これを押すと、以下のようなコンソール画面が立ち上がり、ローカルで起動した関数のURLが表示されます。
このURLに対してJSONを投げると、レスポンスが返ってくることになります。
PowerShellを使って、コマンドでリクエストを投げてみます。
$data = @{
first='Jane'
last='Doe'
}
$json = $data | ConvertTo-Json
Invoke-RestMethod 'http://localhost:7071/api/Function1' -Method POST -Body $json -ContentType 'application/json'
無事、「Hello Jane Doe!」とあいさつしてくれました!
このように、ローカルでも手軽に関数の動作確認を行うことができます。
(ローカルでの実行なので当然、ブレークポイントをつけてデバッグすることなどもできます)
Azureへのデプロイ
ローカルでの動作確認ができたら、いよいよAzureにデプロイです。
プロジェクトのコンテキストメニューに「発行」があるので、それをクリックします。
「Azure 関数アプリ」を選択し、AzureにFunction Appを新規作成するか既存のものを使うかを選び「発行」をクリックします。今回は、新規作成を選択します。
各情報を入力・選択(必要に応じて新規作成)をし、「作成」をクリックします。
今回試したときは一度「発行が失敗しました」というエラーが出てしまいましたが、再度「発行」を押したら無事成功しました。
Azure上の関数の実行
デプロイできたら、実行してみます。
まずは、Azure上の関数のURLを取得するため、管理ポータルを開きます。
Visual Studioのサーバーエクスプローラーから、さきほどデプロイした関数を探し、右クリック→「管理ポータルで開く」をクリックします。
するとブラウザが起動し、ポータルでデプロイした関数が開かれるので、Function1をクリックし、「関数URLの取得」をクリックします。
すると、リクエストを投げる先のURLが表示される(キー情報などを含んだURLになっています)ので、これをコピーして、ローカルでの確認時と同じようにPowerShellでリクエストを投げてみます。
無事、あいさつしてくれました!
Azure上の関数のリモートデバッグ
Azure上の関数にアタッチしてのリモートデバッグもできます。
リモートデバッグをするには、Visual Studio側の設定で「マイコードのみ」の設定を無効にしておく必要があります。
メニューの「デバッグ」→「オプション」より、以下の「マイコードのみを有効にする」のチェックを外します。
この状態で、サーバーエクスプローラーの関数を右クリックし、「デバッガーのアタッチ」をクリックします。
すると、(アタッチに多少時間がかかりますが)ブレークポイントがヒットするようになり、ステップ実行できるようになります。変数の中身などもちゃんと見ることができます。
実際にWebサービスを連携させたあとに、うまく値が渡っているかなど確認するのに便利そうです。
まとめ
Visual Studio 2017でのAzure Functions開発は、作成からデプロイ、実行確認までトータルにサポートされているうえ、慣れ親しんだC#の開発と同じ感覚でできる点が非常に快適です。