チュートリアル: Azure Functions と Visual Studio for Mac の概要

重要

Visual Studio for Mac は、Microsoft の モダン ライフサイクル ポリシーに従って、2024 年 8 月 31 日に廃止される予定です。 引き続き Visual Studio for Mac を使用できますが、VS Code 用の新しい C# 開発キット拡張機能のプレビュー バージョンなど、Mac 上の開発者向けの他のいくつかのオプションがあります。

サポートタイムラインと代替方法の詳細をご確認ください

このラボでは、Visual Studio for Mac を使用して Azure Functions のビルドを開始する方法を学習します。 Azure Functions 開発者が使用できるバインドとトリガーの多くの種類の 1 つを表す、Azure ストレージ テーブルとの統合も行います。

目標

  • ローカルの Azure Functions を作成およびデバッグする
  • Web および Azure ストレージ リソースを統合する
  • 複数の Azure Functions に関連するワークフローを編成する

要件

  • Visual Studio for Mac 7.5 以上。
  • Azure サブスクリプション (https://azure.com/free から無料で入手可能)。

演習 1: Azure Functions プロジェクトの作成

  1. Visual Studio for Mac を起動します。

  2. [ファイル]> [新しいソリューション] の順に選択します。

  3. [クラウド] > [全般] カテゴリから、[Azure Functions] テンプレートを選びます。 Azure Functions をホストする .NET クラス ライブラリを作成する場合は、C# を使用します。 [次へ] をクリックします。

    Azure Functions template selection

  4. [プロジェクト名]"AzureFunctionsLab" に設定して、[作成] をクリックします。

    naming and creating your Azure function project

  5. [ソリューション] ウィンドウでノードを展開します。 既定のプロジェクト テンプレートには、さまざまな Azure WebJobs パッケージと、Newtonsoft.Json パッケージへの NuGet 参照が含まれています。

    次の 3 つのファイルもあります。- ホストのグローバル構成オプションを記述するための host.json - サービス設定を構成するための local.settings.json - プロジェクト テンプレートでは、既定の HttpTrigger も作成します。 このラボの目的上、プロジェクトから HttpTrigger.cs ファイルを削除する必要があります。

    local.settings.json を開きます。 既定では、2 つの空の接続文字列設定が示されます。

    solution window displaying local.settings.json file

演習 2: Azure ストレージ アカウントの作成

  1. https://portal.azure.com で Azure アカウントにログオンします。

  2. [お気に入り] セクションで、画面の左側にある [ストレージ アカウント] を選択します。

    favorites section of Azure portal showing storage accounts item

  3. 次のように、[追加] を選択して新しいストレージ アカウントを作成します。

    Button to add new storage account

  4. [名前] にグローバルに一意の名前を入力し、それを [リソース グループ] で再利用します。 その他のすべての項目は既定値のままでかまいません。

    new storage account details

  5. Create をクリックしてください。 ストレージ アカウントの作成には数分かかる場合があります。 正常に作成された場合は、通知が表示されます。

    deployment successful notification

  6. 通知の [リソースに移動] ボタンを選択します。

  7. [アクセス キー] タブを選択します。

    access key setting

  8. 最初の [接続文字列] をコピーします。 この文字列は、後で Azure Storage と Azure 関数を統合する際に使用されます。

    information for key 1

  9. Visual Studio for Mac に戻り、local.settings.jsonAzureWebJobsStorage 設定として完全な接続文字列を貼り付けます。 これで、リソースへのアクセスを必要とする、関数の属性の設定名を参照することができます。

    local settings file with connection key entered

例 3: Azure 関数の作成とデバッグ

  1. これで、一部のコードの追加を開始する準備ができました。 .NET クラス ライブラリで作業を行う場合は、Azure Functions が静的メソッドとして追加されます。 [ソリューション] ウィンドウで、[AzureFunctions] プロジェクト ノードを右クリックして、[追加] > [関数の追加] を選びます。

    Add function option

  2. [新しい Azure Functions] ダイアログで、Generic Webhook テンプレートを選択します。 次のように、名前Add に設定し、[OK] をクリックして関数を作成します。

    New Azure Functions dialog

  3. 新しいファイルの先頭に、以下の using ディレクティブを追加します。

    using Microsoft.Azure.WebJobs.Extensions.Http;
    using System.Web;
    using Microsoft.WindowsAzure.Storage.Table;
    
  4. 既存の Run メソッドを削除し、Azure 関数としてクラスに以下のメソッドを追加します。

    [FunctionName("Add")]
    public static int Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]
    HttpRequestMessage req,
    TraceWriter log)
    {
        int x = 1;
        int y = 2;
    
        return x + y;
    }
    
  5. ここで、メソッドの定義を 1 つずつ説明していきます。

    最初に表示されるのは FunctionName 属性で、このメソッドを Azure 関数としてマークします。 この属性は関数のパブリック名を指定します。 属性名が、実際のメソッド名と一致する必要はありません。

    New run method with FunctionName attribute highlighted

  6. 次に、メソッドは、必須である public static メソッドとしてマークされます。 また、戻り値が int であることがわかります。メソッド属性を使用して特に指定されていない限り、Azure 関数の非 void 戻り値はテキストとしてクライアントに返されます。 既定では、XML として返されますが、JSON に変更することができます。この操作は、ラボで後から行います。

    New run method with method initialization highlighted

  7. 最初のパラメーターは HttpTrigger 属性でマークされています。これは、このメソッドが HTTP 要求で呼び出されることを示します。 この属性はメソッドの承認レベルと、サポートされる動詞 (ここでは "GET" のみ) も指定します。 必要に応じて、Route を定義することもできます。これにより、メソッドへのパスがオーバーライドされ、パスから自動的に変数を抽出する手段が提供されます。 ここでは Route が null であるため、このメソッドへのパスは既定で /api/Add になります。

    New run method with parameter highlighted

  8. メソッドに対する最後のパラメーターは TraceWriter で、これを使用して診断とエラーのメッセージをログに記録できます。

    New run method with TraceWriter highlighted

  9. 行の余白をクリックして、メソッドの return 行にブレークポイントを設定します。

    Breakpoint set at return line

  10. F5 キーを押すか、[実行] > [デバッグの開始] を選んで、デバッグ セッションでプロジェクトをビルドして実行します。 [実行] ボタンをクリックすることもできます。 これらのオプションではすべて同じタスクが実行されます。 このラボの残りの部分では F5 キーを押しますが、一番使いやすい方法を使用できます。

    Build and Run project

  11. プロジェクトを実行すると、端末アプリケーションが自動的に開きます。

  12. このプロジェクトでは、メソッドの属性と、この記事の後半で説明するファイル規則に基づいて、Azure Functions の検出プロセスを実行します。 この場合、単一の Azure 関数が検出され、1 つのジョブ関数が "生成" されます。

    Output of Azure function in Terminal

  13. Azure Functions ホストは、スタートアップ メッセージの一番下に HTTP トリガー API の URL を出力します。 これは 1 つだけである必要があります。 その URL をコピーし、新しいブラウザー タブで貼り付けます。

    Azure function API URL

  14. ブレークポイントはすぐにトリガーされます。 Web 要求が関数にルーティングされ、デバッグできるようになりました。 x 変数にポインタを合わせると、その値が表示されます。

    Breakpoint triggered

  15. 以前に追加するために使用したのと同じ方法を使って、ブレークポイントを削除します (余白をクリックするか、行を選択して F9 キーを押す)。

  16. F5 キーを押して実行を続行します。

  17. ブラウザーで、メソッドの XML 結果がレンダリングされます。 期待どおりに、ハードコーディングされた加算演算で妥当な合計が生成されます。 Safari で "3" のみが表示されている場合は、Safari > [Preferences]\(環境設定\) > [Advanced]\(詳細\) に移動し、[Show Develop menu in menu bar]\(メニュー バーに開発メニューを表示\) チェック ボックスをオンにしてページを再度読み込みます。

  18. Visual Studio for Mac で、[停止] ボタンをクリックしてデバッグ セッションを終了します。 新しい変更が確実に選択されるように、必ずデバッグ セッションを再開 (停止してから実行) してください。

    Stop debugging option

  19. Run メソッドで、xy の定義を次のコードに置き換えます。 このコードは URL のクエリ文字列から値を抽出し、指定されたパラメーターに基づいて、加算演算を動的に実行できるようにします。

    var query = HttpUtility.ParseQueryString(req.RequestUri.Query);
    
    int x = int.Parse(query["x"]);
    
    int y = int.Parse(query["y"]);
    
    return x + y;
    
  20. アプリケーションを実行します。

  21. ブラウザー ウィンドウに戻り、文字列 /?x=2&y=3 を URL に追加します。 これで URL 全体は http://localhost:7071/api/Add?x=2&y=3 になるはずです。 新しい URL に移動します。

  22. この時点で、結果に新しいパラメーターが反映されるはずです。 プロジェクトを異なる値で自由に実行してください。 エラー チェックが行われていないため、パラメーターが無効であるか欠落している場合、エラーがスローされることに注意してください。

  23. デバッグ セッションを停止します。

演習 4: function.json の操作

  1. 前の演習では、ライブラリに定義されている Azure 関数のジョブ関数が Visual Studio for Mac で生成されたことを示しました。 これは、Azure Functions で実際に実行時にメソッド属性が使用されるのではなく、コンパイル時のファイル システム規則を使用して、Azure Functions を利用可能にする場所と方法を構成するためです。 [ソリューション] ウィンドウで、プロジェクト ノードを右クリックし、[Finder で表示] を選択します。

    Reveal in Finder menu option

  2. bin/Debug/netstandard2.0 に到達するまで、ファイル システムを下に移動します。 Add という名前のフォルダーがあるはずです。 このフォルダーは、C# コードの関数名属性に対応するように作成されています。 Add フォルダーを展開して、単一の function.json ファイルを表示します。 このファイルは、Azure 関数のホストと管理のためにランタイムによって使用されます。 コンパイル時サポートのないその他の言語モデル (C# スクリプトや JavaScript など) の場合は、これらのフォルダーを手動で作成して管理する必要があります。 C# 開発者向けには、ビルド時に属性メタデータから自動的に生成されます。 function.json を右クリックして選択し、Visual Studio で開きます。

    function.json in the file directory

  3. このチュートリアルの前の手順を実行している場合は、C# 属性の基本的な知識があるはずです。 それを考えれば、この JSON は見慣れたものです。 ただし、前の演習では説明されていない項目がいくつかあります。 たとえば、binding にはそれぞれ direction が設定されている必要があります。 お察しのとおり、"in" はパラメーターが入力されていることを意味し、"out" はパラメーターが戻り値 ($return 経由)、またはメソッドに対する out パラメーターであることを示します。 アセンブリ内には、scriptFile (この最終的な場所に対して相対的) および entryPoint メソッド (パブリックまたは静的) を指定する必要もあります。 次のいくつかの手順では、このモデルを使用してカスタム関数パスを追加するため、このファイルの内容をクリップボードにコピーします。

    function.json file open in Visual Studio for mac

  4. [ソリューション] ウィンドウで、AzureFunctionsLab プロジェクト ノードを右クリックし、[追加] > [新しいフォルダー] を選びます。 新しいフォルダーに Adder という名前を付けます。 既定の規則では、このフォルダーの名前で、api/Adder などの API へのパスが定義されます。

    New folder option

  5. Adder フォルダーを右クリックし、[追加] > [新しいファイル] を選びます。

    New file option

  6. [Web] カテゴリ、[空の JSON ファイル] テンプレートの順に選択します。 [名前]function に設定して、[新規] をクリックします。

    Empty json file option

  7. (手順 3 の) その他の function.json の内容を、新しく作成されたファイルの既定の内容に貼り付けて置き換えます。

  8. json ファイルの先頭から、次の行を削除します。

    "configurationSource":"attributes",
    "generatedBy":"Microsoft.NET.Sdk.Functions-1.0.13",
    
  9. 最初のバインドの末尾 ("name": "req" 行の後) に、以下のプロパティを追加します。 前の行には必ずコンマを含めてください。 このプロパティによって既定のルートがオーバーライドされ、パスから int パラメーターが抽出され、x および y という名前のメソッド パラメーターに配置されるようになります。

    "direction": "in",
    "route": "Adder/{x:int?}/{y:int?}"
    
  10. 最初のバインドの下に別のバインドを追加します。 このバインドは関数の戻り値を処理します。 前の行には必ずコンマを含めてください。

    {
    "name": "$return",
    "type": "http",
    "direction": "out"
    }
    
  11. また、以下に示すように、"Add2" というメソッドを使用するように、ファイルの末尾の entryPoint プロパティを更新します。 これは、api/Adder... というパスが、任意の名前 (ここでは Add2) を持つ適切なメソッドにマップできたことを示すためのもです。

    "entryPoint": "<project-name>.<function-class-name>.Add2"
    
  12. 最終的な function.json ファイルは、次の json のようになります。

    {
    "bindings": [
        {
        "type": "httpTrigger",
        "methods": [
            "get"
        ],
        "authLevel": "function",
        "direction": "in",
        "name": "req",
        "route": "Adder/{x:int?}/{y:int?}"
        },
        {
        "name": "$return",
        "type": "http",
        "direction": "out"
        }
    ],
    "disabled": false,
    "scriptFile": "../bin/AzureFunctionsProject.dll",
    "entryPoint": "AzureFunctionsProject.Add.Add2"
    }
    
  13. このすべての作業を完了するために必要な最後の 1 つの手順は、このファイルを、変更のたびに出力ディレクトリの同じ相対パスにコピーするよう Visual Studio for Mac に指示することです。 ファイルを選択した状態で、右側のバーから [プロパティ] タブを選び、[出力ディレクトリにコピー][新しい場合はコピーする] を選択します。

    Properties options for json file

  14. 予期される関数を実行するために、Add.csRun メソッド (属性を含む) を次のメソッドに置き換えます。 属性が使用されないことと、xy の明示的なパラメーターを持つことを除けば、Run と非常に似ています。

    public static int Add2(
        HttpRequestMessage req,
        int x,
        int y,
        TraceWriter log)
    {
        return x + y;
    }
    
  15. F5 キーを押し、プロジェクトをビルドして実行します。

  16. ビルドが完了し、プラットフォームがスピンアップすると、新しく追加されたメソッドにマップされる要求に対して使用可能な 2 番目のルートがあることが示されます。

    URL for HTTP functions

  17. ブラウザー ウィンドウに戻り、http://localhost:7071/api/Adder/3/5 に移動します。

  18. この時点でメソッドが再び動作し、パスからパラメーターがプルされ、合計が生成されます。

  19. Visual Studio for Mac に戻り、デバッグ セッションを終了します。

演習 5: Azure Storage テーブルの操作

多くの場合、ビルドするサービスは、これまでビルドしたものよりはるかに複雑で、実行にはかなりの時間またはインフラストラクチャが必要になることがあります。 その場合、リソースが利用可能になったときに処理のためキューに入れられた要求を受け入れることが効果的な場合があります。これは Azure Functions でサポートされています。 それ以外の場合は、一元的にデータを格納します。 Azure Storage のテーブルで、この操作をすばやく行うことができます。

  1. 以下のクラスを Add.cs に追加します。 これは名前空間の中に記述すべきですが、ここでは既存のクラスの外に記述します。

    public class TableRow : TableEntity
    {
        public int X { get; set; }
        public int Y { get; set; }
        public int Sum { get; set; }
    }
    
  2. Add クラス内で、次のコードを追加して別の関数を導入します。 これは HTTP 応答を伴わないという点で、これまでとは異なることに注意してください。 最終行は、パラメーターと合計だけでなく、後で簡単に取得できるようにする一部のキー情報 (PartitionKeyRowKey) が入力された新しい TableRow を返します。 また、メソッド内のコードでは、関数がいつ実行されるかをより簡単に把握できるように TraceWriter が使用されます。

    [FunctionName("Process")]
    [return: Table("Results")]
    public static TableRow Process(
        [HttpTrigger(AuthorizationLevel.Function, "get",
            Route = "Process/{x:int}/{y:int}")]
        HttpRequestMessage req,
        int x,
        int y,
        TraceWriter log)
    {
        log.Info($"Processing {x} + {y}");
    
        return new TableRow()
        {
            PartitionKey = "sums",
            RowKey = $"{x}_{y}",
            X = x,
            Y = y,
            Sum = x + y
        };
    }
    
  3. F5 キーを押し、プロジェクトをビルドして実行します。

  4. ブラウザー タブで、http://localhost:7071/api/Process/4/6 に移動します。 これにより別のメッセージがキューに入れられ、最終的には別の行がテーブルに追加されます。

  5. 端末に戻り、4 + 6 の受信要求を監視します。

    Terminal output showing addition request

  6. ブラウザーに戻り、同じ URL への要求を更新します。 この時点で、Process メソッドの後にエラーが表示されます。 これは、コードが、既に存在するパーティションと行キーの組み合わせを使用して、Azure Table Storage テーブルに行を追加しようとしているためです。

    System.Private.CoreLib: Exception while executing function: Process. Microsoft.Azure.WebJobs.Host: Error while handling parameter $return after function returned:. Microsoft.Azure.WebJobs.Host: The specified entity already exists.

  7. デバッグ セッションを終了します。

  8. エラーを軽減するには、TraceWriter パラメーターの直前のメソッド定義に次のパラメーターを追加します。 このパラメーターは、結果を格納するために使用していた PartitionKeyResults テーブルから TableRow の取得を試みるよう Azure Functions プラットフォームに指示します。 ただし、本当の魔法のいくつかは、まったく同じメソッドの他の x および y パラメーターに基づいて RowKey が動的に生成されていることに気付いたときに起こります。 その行が既に存在する場合、開発者に必要な追加作業が行われずにメソッドが開始されたときに、tableRow に含まれます。 行が存在しない場合は、null だけとなります。 このような効率性により、開発者はインフラストラクチャではなく、重要なビジネス ロジックに集中することができます。

    [Table("Results", "sums", "{x}_{y}")]
    TableRow tableRow,
    
  9. メソッドの先頭に次のコードを追加します。 tableRow が null でない場合、演算結果は既に要求されており、すぐに返すことができます。 それ以外の場合、関数は以前のとおりに続行します。 これはデータを返す最も堅牢な方法でないかもしれませんが、わずかなコードで複数のスケーラブル層にわたる非常に洗練された演算を編成できることを示しています。

    if (tableRow != null)
    {
        log.Info($"{x} + {y} already exists");
        return null;
    }
    
  10. F5 キーを押し、プロジェクトをビルドして実行します。

  11. ブラウザー タブで、http://localhost:7071/api/Process/4/6 の URL を更新します。 このレコードのテーブル行は存在するため、エラーなしですぐに返されます。 HTTP 出力はないため、端末で出力を確認できます。

    Terminal output showing table row already exists

  12. URL を更新し、http://localhost:7071/api/Process/5/7 など、まだテストされていない組み合わせを反映させます。 テーブル行が (予期したとおりに) 見つからなかったことを示す、端末のメッセージに注意してください。

    Terminal output showing new process

  13. Visual Studio for Mac に戻り、デバッグ セッションを終了します。

まとめ

このラボでは、Visual Studio for Mac で Azure Functions のビルドを開始する方法を学習しました。