次の方法で共有


Visual Studio を使用する Azure Functions の開発

Visual Studio で、C# クラス ライブラリ関数を開発して、テストし、Azure にデプロイすることができます。 Azure Functions を初めて使用する場合は、「Azure Functions の概要」を参照してください。

すぐに始めるには、Visual Studio での関数のクイックスタートを最後まで行うことをお勧めします。

この記事では、Visual Studio を使って C# クラス ライブラリ関数を開発して Azure に発行する方法に関する詳細情報を提供します。 C# クラス ライブラリ関数の開発には、分離ワーカー モデルインプロセス モデルの 2 つのモデルがあります。

今お読みになっているのは、この記事の分離ワーカー モデル バージョンです。 記事の先頭で、好みのモデルを選択できます。

今お読みになっているのは、この記事のインプロセス モデル バージョンです。 記事の先頭で、好みのモデルを選択できます。

特に明記されていない限り、ここで示す手順と例は Visual Studio 2022 のものです。 Visual Studio 2022 リリースの詳細については、リリース ノートまたはプレビュー リリース ノートを参照してください。

前提条件

  • Azure の開発ワークロードを含む Visual Studio 2022。

  • Azure Storage アカウントなど、他の必要なリソースは、発行プロセス中にサブスクリプションに作成されます。

  • Azure サブスクリプションをお持ちでない場合は、開始する前に Azure 無料アカウントを作成してください。

Azure Functions プロジェクトを作成する

Visual Studio の Azure Functions プロジェクト テンプレートを使用すると、Azure の関数アプリに発行できる C# クラス ライブラリ プロジェクトを作成できます。 関数アプリを使用すると、リソースの管理、デプロイ、スケーリング、および共有を容易にするための論理ユニットとして関数をグループ化できます。

  1. Visual Studio メニューで、 [ファイル]>[新規]>[プロジェクト] を選択します。

  2. [新しいプロジェクトの作成] の検索ボックスに「functions」と入力し、Azure Functions テンプレートを選択してから、 [次へ] を選択します。

  3. [新しいプロジェクトの構成] で、プロジェクトのプロジェクト名を入力し、 [作成] を選択します。 関数アプリ名は、C# 名前空間として有効である必要があります。そのため、アンダースコア、ハイフン、その他の英数字以外の文字は使用しないでください。

  4. [新しい Azure Functions アプリケーションの作成] 設定で、次の表の値を使用します。

    設定 説明
    .NET のバージョン .NET 6 Isolated この値により、分離ワーカー プロセスで実行される関数プロジェクトが作成されます。 分離ワーカー プロセスでは、.NET の他の LTS 以外のバージョンと、.NET Framework もサポートされます。 詳細については、「Azure Functions ランタイム バージョンをターゲットにする方法」をご覧ください。
    関数テンプレート HTTP トリガー この値は、HTTP 要求によってトリガーされる関数を作成します。
    ストレージ アカウント (AzureWebJobsStorage) ストレージ エミュレーター Azure の関数アプリにはストレージ アカウントが必要であるため、プロジェクトを Azure に発行する際に割り当てられるか、作成されます。 HTTP トリガーによって、Azure Storage アカウントの接続文字列が使用されることはありません。その他のすべてのトリガーの種類には、有効な Azure Storage アカウントの接続文字列が必要です。
    承認レベル 匿名 作成される関数を、すべてのクライアントがキーを使用せずにトリガーできます。 この承認設定により、新しい関数のテストが容易になります。 詳細については、「認可レベル」を参照してください。

    Azure Functions プロジェクト設定のスクリーンショット

    設定 説明
    .NET のバージョン .NET 6 この値により、Azure Functions ランタイムのバージョン 4.x でインプロセスを実行する関数プロジェクトが作成されます。 詳細については、「Azure Functions ランタイム バージョンをターゲットにする方法」をご覧ください。
    関数テンプレート HTTP トリガー この値は、HTTP 要求によってトリガーされる関数を作成します。
    ストレージ アカウント (AzureWebJobsStorage) ストレージ エミュレーター Azure の関数アプリにはストレージ アカウントが必要であるため、プロジェクトを Azure に発行する際に割り当てられるか、作成されます。 HTTP トリガーによって、Azure Storage アカウントの接続文字列が使用されることはありません。その他のすべてのトリガーの種類には、有効な Azure Storage アカウントの接続文字列が必要です。
    承認レベル 匿名 作成される関数を、すべてのクライアントがキーを使用せずにトリガーできます。 この承認設定により、新しい関数のテストが容易になります。 詳細については、「認可レベル」を参照してください。

    Azure Functions プロジェクト設定のスクリーンショット

    [承認レベル][匿名] に設定していることを確認します。 関数の既定のレベルを選択した場合、関数エンドポイントにアクセスする要求で、関数キーを提示する必要があります。

  5. [作成] を選択して、関数プロジェクトと HTTP トリガー関数を作成します。

Azure Functions プロジェクトを作成した後、プロジェクト テンプレートを使って C# プロジェクトを作成し、Microsoft.Azure.Functions.WorkerMicrosoft.Azure.Functions.Worker.Sdk の NuGet パッケージをインストールして、ターゲット フレームワークを設定します。

Azure Functions プロジェクトを作成した後、プロジェクト テンプレートを使用して C# プロジェクトを作成し、Microsoft.NET.Sdk.Functions NuGet パッケージをインストールし、ターゲット フレームワークを設定します。

新しいプロジェクトには次のファイルが含まれます。

  • host.json:Functions のホストを構成できます。 これらの設定は、ローカルでの実行時と Azure での実行時の両方に適用されます。 詳細については、host.json のリファレンスを参照してください。

  • local.settings.json:関数をローカルで実行するときに使用される設定を保持します。 Azure で実行している場合、これらの設定は使用されません。 詳細については、「ローカル設定ファイル」を参照してください。

    重要

    local.settings.json ファイルにはシークレットを含めることができるため、それをプロジェクト ソース管理から除外する必要があります。 このファイルの [出力ディレクトリにコピー] 設定が [新しい場合はコピーする] に設定されていることを確認します。

詳しくは、分離ワーカー ガイドの「プロジェクト構造」をご覧ください。

詳細については、「関数クラス ライブラリ プロジェクト」を参照してください。

ローカルでアプリの設定を操作する

Azure の関数アプリで実行する場合、関数に必要な設定はアプリ設定に安全に保存されます。 ローカル開発中は、これらの設定は代わりに local.settings.json ファイルの Values コレクションに追加されます。 local.settings.json ファイルには、ローカルの開発ツールによって使用される設定も格納されます。

プロジェクトの local.settings.json ファイルの Values コレクションにある項目は、Azure の関数アプリのアプリケーション設定にある項目をミラー化するためのものです。

プロジェクトを発行しても、Visual Studio では local.settings.json の設定が自動的にアップロードされません。 これらの設定が Azure の Function App にも確実に存在するようにするには、プロジェクトを発行した後にそれらをアップロードします。 詳細については、「Function App の設定」を参照してください。 ConnectionStrings コレクション内の値は発行されません。

コードを使用して、Function App の設定値を環境変数として読み取ることもできます。 詳細については、「環境変数」を参照してください。

ローカル開発用のプロジェクトを構成する

Functions ランタイムでは内部的に Azure Storage アカウントを使用します。 HTTP と Webhook 以外のすべてのトリガーの種類について、Values.AzureWebJobsStorage キーを有効な Azure Storage アカウントの接続文字列に設定します。 関数アプリでは、プロジェクトで必要な AzureWebJobsStorage 接続設定に Azure エミュレーターを使うこともできます。 エミュレーターを使用するには、AzureWebJobsStorage の値を UseDevelopmentStorage=true に設定します。 この設定は、デプロイ前に実際のストレージ アカウント接続文字列に変更します。 詳細については、ローカル ストレージ エミュレーターに関するページを参照してください。

ストレージ アカウントの接続文字列を設定するには、次のようにします。

  1. Azure Portal のストレージ アカウントに移動します。

  2. [アクセス キー] タブの [セキュリティ + ネットワーク] の下にある key1接続文字列をコピーします。

  3. プロジェクトで、local.settings.json ファイルを開き、コピーした接続文字列に AzureWebJobsStorage キーの値を設定します。

  4. 前の手順を繰り返し、関数に必要なその他のすべての接続について、Values 配列に一意のキーを追加します。

プロジェクトに関数を追加する

C# クラス ライブラリ関数では、関数で使用されるバインドはコードで属性を適用することで定義されます。 提供されているテンプレートから関数トリガーを作成する場合は、トリガー属性が適用されます。

  1. [ソリューション エクスプローラー] で、プロジェクト ノードを右クリックして [追加]>[新しい Azure 関数] を選びます。

  2. クラスの [名前] を入力してから、[追加] を選びます。

  3. トリガーを選び、必要なバインド プロパティを設定して、[追加] を選びます。 次の例は、Queue storage トリガー関数を作成する場合の設定を示しています。

    Queue storage トリガー関数を作成する

    Azure Storage サービス トリガーの場合は、[接続の構成] ボックスをオンにすると、Azurite ストレージ エミュレーターの使用、またはプロビジョニングされた Azure ストレージ アカウントの参照のいずれかの選択を求められます。 [次へ] を選ぶと、ストレージ アカウントを選んだ場合は、Visual Studio によって Azure アカウントへの接続と接続文字列の取得が試みられます。 [Save connection string value in Local user secrets file] (ローカル ユーザー シークレット ファイルに接続文字列の値を保存する) をオンにしてから、[完了] を選んでトリガー クラスを作成します。

    このトリガーの例では、QueueStorage という名前のキーを使うストレージ接続に対するアプリケーション設定を使います。 local.settings.json ファイルに保存されているこのキーでは、Azurite エミュレーターまたは Azure ストレージ アカウントを参照します。

  4. 新しく追加されたクラスを確認します。 たとえば、次の C# クラスは基本的な Queue storage トリガー関数を表します。

    Function という属性が設定された静的な Run() メソッドがあります。 この属性は、メソッドが関数のエントリ ポイントであることを示します。

    using System;
    using Azure.Storage.Queues.Models;
    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.Logging;
    
    namespace Company.Function
    {
        public class QueueTriggerCSharp
        {
            private readonly ILogger<QueueTriggerCSharp> _logger;
    
            public QueueTriggerCSharp(ILogger<QueueTriggerCSharp> logger)
            {
                _logger = logger;
            }
    
            [Function(nameof(QueueTriggerCSharp))]
            public void Run([QueueTrigger("PathValue", Connection = "ConnectionValue")] QueueMessage message)
            {
                _logger.LogInformation($"C# Queue trigger function processed: {message.MessageText}");
            }
        }
    }
    

    FunctionName という属性が設定された静的な Run() メソッドがあります。 この属性は、メソッドが関数のエントリ ポイントであることを示します。

    using System;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Host;
    using Microsoft.Extensions.Logging;
    
    namespace Company.Function
    {
        public class QueueTriggerCSharp
        {
            [FunctionName("QueueTriggerCSharp")]
            public void Run([QueueTrigger("PathValue", Connection = "ConnectionValue")]string myQueueItem, ILogger log)
            {
                log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
            }
        }
    }
    

バインド固有の属性は、エントリ ポイント メソッドに指定された各バインド パラメーターに適用されます。 属性ではパラメーターとしてバインド情報を取ります。 前の例では、Queue storage トリガー関数を示す QueueTrigger 属性が最初のパラメーターに適用されています。 キュー名および接続文字列の設定名は、パラメーターとして QueueTrigger 属性に渡されます。 詳細については、Azure Functions での Azure Queue ストレージのバインドに関する記事を参照してください。

上記の手順を使用して、複数の関数を Function App プロジェクトに追加します。 プロジェクト内の各関数で異なるトリガーを使用できますが、1 つの関数には 1 つのトリガーのみを使用する必要があります。 詳しくは、「Azure Functions でのトリガーとバインドの概念」をご覧ください。

バインドを追加する

トリガーと同じように、入力バインドと出力バインドも、バインド属性として関数に追加されます。 以下のように、関数にバインドを追加します。

  1. プロジェクトをローカル開発用に構成していることを確認します。

  2. バインドの参照記事でバインド固有のNuGet パッケージ要件を見つけることで、特定のバインドに適したNuGet拡張パッケージを追加します。 たとえば、Event Hubs トリガーのパッケージ要件については、Event Hubs のバインドの参照記事を参照してください。

  3. パッケージ マネージャー コンソールで次のコマンドを使用して、特定のパッケージをインストールします。

    Install-Package Microsoft.Azure.Functions.Worker.Extensions.<BINDING_TYPE> -Version <TARGET_VERSION>
    
    Install-Package Microsoft.Azure.WebJobs.Extensions.<BINDING_TYPE> -Version <TARGET_VERSION>
    

    この例では、<BINDING_TYPE> をバインド拡張機能に固有の名前に置き換え、<TARGET_VERSION>4.0.0 などの特定のバージョンのパッケージに置き換えます。 有効なバージョンは、NuGet.org の個々のパッケージ ページに記載されています。

  4. バインドが必要なアプリ設定がある場合は、ローカル設定ファイルValues コレクションに追加します。

    この関数では、ローカルで実行するときにこれらの値を使用します。 関数が Azure の Function App で実行される場合は、Function App の設定が使用されます。 Visual Studio を使うと、簡単にローカル設定を Azure に発行できます。

  5. 適切なバインド属性をメソッド シグネチャに追加します。 次の例では、キュー メッセージによって関数がトリガーされ、出力バインドによって、同じテキストの新しいキュー メッセージが別のキューに作成されます。

     public class QueueTrigger
    {
        private readonly ILogger _logger;
    
        public QueueTrigger(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<QueueTrigger>();
        }
    
        [Function("CopyQueueMessage")]
        [QueueOutput("myqueue-items-destination", Connection = "QueueStorage")]
        public string Run([QueueTrigger("myqueue-items-source", Connection = "QueueStorage")] string myQueueItem)
        {
            _logger.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
            return myQueueItem;
        }
    }
    

    QueueOutput 属性は、メソッドでのバインドを定義します。 複数の出力バインディングの場合は、代わりに、返されるオブジェクトの文字列プロパティでこの属性を指定します。 詳しくは、「複数の出力バインディング」をご覧ください。

    public static class SimpleExampleWithOutput
    {
        [FunctionName("CopyQueueMessage")]
        public static void Run(
            [QueueTrigger("myqueue-items-source", Connection = "QueueStorage")] string myQueueItem, 
            [Queue("myqueue-items-destination", Connection = "QueueStorage")] out string myQueueItemCopy,
            ILogger log)
        {
            log.LogInformation($"CopyQueueMessage function processed: {myQueueItem}");
            myQueueItemCopy = myQueueItem;
        }
    }
    

    out パラメーターの Queue 属性は、出力バインディングを定義します。

    Queue Storage への接続は、QueueStorage 設定から取得されます。 詳しくは、特定のバインドの参照記事をご覧ください。

Functions でサポートされるバインドを網羅した一覧については、「サポートされるバインディング」を参照してください。

関数をローカルで実行する

Azure Functions Core Tools を使用すると、ローカルの開発用コンピューター上で Azure Functions プロジェクトを実行できます。 Functions プロジェクトをデバッグするために F5 キーを押すと、ローカル Functions ホスト (func.exe) が起動し、ローカル ポート (通常は 7071) をリッスンします。 呼び出し可能な関数エンドポイントが出力に書き込まれるので、それらのエンドポイントを関数のテストに使用できます。 詳細については、「Azure Functions Core Tools の操作」を参照してください。 Visual Studio から初めて関数を起動すると、これらのツールをインストールするよう求めるメッセージが表示されます。

Visual Studio のデバッグ モードで関数を開始するには、次のようにします。

  1. F5 キーを押す。 メッセージが表示されたら、Visual Studio からの要求に同意し、Azure Functions Core (CLI) ツールをダウンロードしてインストールします。 また、ツールで HTTP 要求を処理できるように、ファイアウォールの例外を有効にすることが必要になる場合もあります。

  2. プロジェクトを実行して、デプロイ済みの関数をテストする場合と同じようにコードをテストします。

    Visual Studio をデバッグ モードで実行すると、想定どおりにブレークポイントにヒットします。

Visual Studio を使用したテストに関する詳細なシナリオについては、「関数のテスト」を参照してください。

Azure に発行する

関数プロジェクトを Azure に発行すると、Visual Studio は ZIP デプロイを使ってプロジェクト ファイルをデプロイします。 可能な場合は、プロジェクトがデプロイ (.zip) パッケージ内で実行されるように、[Run-From-Package] (パッケージから実行) も選ぶ必要があります。 詳しくは、「Azure でパッケージ ファイルから関数を実行する」をご覧ください。

Web 配置 (msdeploy) を使って Azure Functions にデプロイしないでください。

次の手順を使用して、プロジェクトを Azure の Function App に発行します。

  1. ソリューション エクスプローラーで、プロジェクトを右クリックし、 [発行] を選択します。 [ターゲット][Azure] を選択した後、[次へ] を選択します。

    発行ペインのスクリーンショット。

  2. [特定のターゲット][Azure Function App (Windows)] を選択します。 Windows で実行される関数アプリが作成されます。 [次へ] を選択します。

    特定のターゲットを持つ [発行] ペインのスクリーンショット。

  3. [Functions インスタンス][新しい Azure 関数の作成] を選択します。

    [新しい関数アプリ インスタンスの作成] を示すスクリーンショット。

  4. 次の表に示されている値を使用して、新しいインスタンスを作成します。

    設定 内容
    名前 グローバルに一意の名前 新しい関数アプリを一意に識別する名前。 この名前をそのまま使用するか、新しい名前を入力します。 有効な文字は、a-z0-9- です。
    サブスクリプション 該当するサブスクリプション 使用する Azure サブスクリプション。 このサブスクリプションを承諾するか、ドロップダウン リストから新しいものを選択します。
    リソース グループ リソース グループの名前 関数アプリを作成するリソース グループ。 [新規作成] を選択して、新しいリソース グループを作成します。 ドロップダウン リストから既存のリソース グループを選んで使うこともできます。
    プランの種類 従量課金 従量課金プランで実行される関数アプリにプロジェクトを発行する場合は、関数アプリの実行に対してのみお支払いください。 他のホスティング プランでは、コストが高くなります。
    場所 App Service の場所 自分の近く、または関数がアクセスする他のサービスの近くの Azure リージョンで、[場所] を選びます。
    Azure ストレージ 汎用ストレージ アカウント Functions の共通言語ランタイムでは、Azure ストレージ アカウントが必要です。 [新規] を選択して汎用ストレージ アカウントを構成します。 ストレージ アカウントの要件を満たす既存のアカウントを選択することもできます。
    Application Insights Application Insights インスタンス 関数アプリの Azure Application Insights 統合を有効にする必要があります。 新規または既存の Log Analytics ワークスペースで、[新規作成] を選択して新しいインスタンスを作成します。 既存のインスタンスを選んで使うこともできます。

    [App Service の作成] ダイアログのスクリーンショット。

  5. [作成] を選択して、関数アプリとその関連リソースを Azure で作成します。 リソース作成の状態はウィンドウの左下に表示されます。

  6. [Functions インスタンス] で、[パッケージ ファイルから実行する] チェックボックスがオンになっていることを確認します。 関数アプリは、Zip Deploy を使用して、Run-From-Package モードが有効な状態でデプロイされます。 Zip Deploy は関数プロジェクトの推奨されるデプロイ方法であり、高いパフォーマンスを実現できます。

    [プロファイル作成の完了] ペインのスクリーンショット。

  7. [完了] を選択し、[発行] ペインで [発行] を選択して、プロジェクト ファイルを含むパッケージを Azure 内の新しい関数アプリにデプロイします。

    デプロイが完了すると、Azure 内の関数アプリのルート URL が [発行] タブに表示されます。

  8. [発行] タブの [ホスティング] セクションで、[Azure portal で開く] を選択します。 新しい関数アプリの Azure リソースが Azure portal で開きます。

    [発行の成功] メッセージのスクリーンショット。

Function App の設定

Visual Studio では、プロジェクトを発行するときにこれらの設定が自動的にアップロードされることはありません。 local.settings.json に追加したすべての設定は、Azure の関数アプリにも追加する必要があります。

Azure の関数アプリに必要な設定をアップロードする最も簡単な方法は、[ホスティング] セクションの横にある 3 つの点を展開し、プロジェクトが正常に発行された後に表示される [Azure App Service の設定を管理する] リンクを選択することです。

[発行] ウィンドウの設定

このリンクを選択すると、Function App の [アプリケーションの設定] ダイアログが表示され、ここで新しいアプリケーション設定を追加したり、既存の設定を変更したりできます。

アプリケーションの設定

[ローカル] には local.settings.json ファイルの設定値が表示され、 [リモート] には Azure の Function App の現在の設定値が表示されます。 新しいアプリ設定を作成するには、 [設定の追加] を選択します。 [ローカルから値を挿入する] リンクを使用して、設定値を [リモート] フィールドにコピーします。 [OK] を選択すると、保留中の変更がローカル設定ファイルと Function App に書き込まれます。

Note

既定では、local.settings.json ファイルはソース管理にチェックインされません。 これは、ソース管理からローカル関数プロジェクトを複製するときに、プロジェクトに local.settings.json ファイルがないことを意味します。 この場合、 [アプリケーション設定] ダイアログが期待どおりに動作するように、プロジェクトのルートに local.settings.json ファイルを手動で作成する必要があります。

以下のいずれかの方法を使用して、アプリケーション設定を管理することもできます。

Remote Debugging

関数アプリをリモートでデバッグするには、プロジェクトのデバッグ構成を発行する必要があります。 また、Azure の関数アプリでリモート デバッグを有効にする必要もあります。

このセクションでは、リリース構成を使用して関数アプリに既に発行していることを前提としています。

リモート デバッグに関する考慮事項

  • 運用環境のサービスでは、リモート デバッグはお勧めしません。
  • マイ コードのみのデバッグを有効にしている場合は、無効にします。
  • リモート デバッグ時、ブレークポイントで長時間停止させることは避けてください。 数分以上停止しているプロセスは、応答していないプロセスと見なされ、Azure によりシャットダウンされます。
  • デバッグ中は、サーバーから Visual Studio にデータが送信されるため、帯域幅の使用料に影響が及ぶ可能性があります。 帯域幅使用料については、 Azure 料金計算ツールを参照してください。
  • リモート デバッグは、関数アプリで 48 時間後に自動的に無効になります。 48 時間後に、リモート デバッグを再度有効化する必要があります。

デバッガーをアタッチする

デバッガーをアタッチする方法は、実行モードによって異なります。 分離ワーカー プロセス アプリをデバッグする場合、現在はリモート デバッガーを別の .NET プロセスにアタッチする必要があり、その他にもいくつかの構成手順が必要です。

完了したら、リモート デバッグを無効にする必要があります。

Functions ホストとは別のプロセスで動作している Function アプリにリモート デバッガーをアタッチするには、次のようにします。

  1. [発行] タブの [ホスティング] セクションで省略記号 (...) を選択し、[発行プロファイルのダウンロード] を選択します。 この操作により、発行プロファイルのコピーがダウンロードされ、ダウンロード場所が開きます。 このファイルは必須で、Azure で実行されている分離ワーカー プロセスにアタッチするために使用される資格情報が含まれています。

    注意事項

    .publishettings ファイルには、関数アプリを管理するために使用される認証情報 (エンコードされていない) が含まれています。 このファイルのセキュリティ上のベスト プラクティスは、ソース ディレクトリの外 (例えばLibrariesDocuments フォルダー) に一時的に保存し、不要になった後に削除することです。 悪意のあるユーザーが .publishsettings ファイルへのアクセス許可を取得すると、関数アプリを編集、作成、削除できるためです。

  2. 再度、[発行] タブの [ホスティング] セクションで省略記号 (...) を選択し、[デバッガーのアタッチ] を選択します。

    Visual Studio からデバッガーをアタッチ中のスクリーンショット。

    Visual Studio は関数アプリに接続し、まだ有効になっていない場合はリモート デバッグを有効にします。

    Note

    リモート デバッガーはホスト プロセスに接続できないため、エラーが表示される可能性があります。 いずれの場合も、既定のデバッグはコードを中断しません。

  3. Visual Studio に戻り、[発行] ページの [ホスティング] の下にある [サイト] の URL をコピーします。

  4. [デバッグ] メニューから [プロセスにアタッチ] を選択し、[プロセスにアタッチ] ウィンドウで、URL を [接続先] に貼り付け、https:// を削除してポート :4024 に追加します。

    ターゲットが <FUNCTION_APP>.azurewebsites.net:4024 と表示されることを確認し、[Enter] キーを押します。

    Visual Studio のプロセス ダイアログへのアタッチ

  5. メッセージが表示されたら、ローカル ファイアウォール経由で Visual Studio へのアクセスを許可します。

  6. 資格情報の入力を求められた場合、ローカル ユーザーの資格情報ではなく、別のアカウントを選択します (Windows ではその他の選択肢)。 Windows の認証ダイアログで、[メールアドレス][パスワード]に発行プロファイルのuserNameuserPWDの値を指定します。 デプロイ サーバーとのセキュリティで保護された接続が確立されると、使用可能なプロセスが表示されます。

    Visual Studio で資格情報を入力

  7. [すべてのユーザーからのプロセスを表示する] を選択し、[dotnet.exe] を選択して [アタッチ] を選択します。 操作が完了すると、分離ワーカー プロセスで実行されている C# クラス ライブラリ コードにアタッチされます。 この時点で、関数アプリを通常どおりにデバッグできます。

Functions ホストを使用してインプロセスで実行されている関数アプリにリモート デバッガーをアタッチするには、次のようにします。

  • [発行] タブの [ホスティング] セクションで省略記号 (...) を選択し、[デバッガーのアタッチ] を選択します。

    Visual Studio からデバッガーをアタッチ中のスクリーンショット。

Visual Studio は関数アプリに接続し、まだ有効になっていない場合はリモート デバッグを有効にします。 また、アプリのホスト プロセスにデバッガーを見つけてアタッチします。 この時点で、関数アプリを通常どおりにデバッグできます。

リモート デバッグの無効化

コードのリモート デバッグが完了したら、Azure portal でリモート デバッグを無効にする必要があります。 リモート デバッグは、忘れた場合でも 48 時間後に自動的に無効になります。

  1. プロジェクトの [発行] タブで、[ホスティング] セクションで省略記号 (...) を選択し、[Azure Portal で開く] を選択します。 このアクションにより、プロジェクトのデプロイ先の Azure portal で関数アプリが開きます。

  2. 関数アプリの、[設定][構成] を選択し、[全般設定] を選択し、[リモート デバッグ]オフ に設定して、[保存] を選択して [続行] を選択します。

関数アプリの再起動後、リモート プロセスにリモート接続できなくなります。 同じタブを Azure portal で使用して、Visual Studio の外部でリモート デバッグを有効できます。

関数の監視

関数の実行を監視するための推奨される方法は、Function App を Azure Application Insights と統合することです。 Visual Studio の発行時に関数アプリを作成するときは、この統合を有効にする必要があります。

何らかの理由で発行時に統合が行われなかった場合でも、Azure での関数アプリ用に Application Insights の統合を有効にする必要があります。

Application Insights を使用した監視の詳細については、「Azure Functions を監視する」を参照してください。

関数のテスト

このセクションでは、xUnit を使ってテストできる C# インプロセス モデル プロジェクトを作成する方法について説明します。

Visual Studio で C# を使って Azure Functions をテストする

1. セットアップ

次の手順のようにして、テストをサポートするために必要な、アプリ プロジェクトや関数などの環境を構成します。

  1. 新しい関数アプリを作成して Functions という名前を付けます
  2. テンプレートから HTTP 関数を作成して MyHttpTrigger という名前を付けます。
  3. テンプレートからタイマー関数を作成して MyTimerTrigger という名前を付けます。
  4. ソリューションで xUnit テスト アプリを作成して Functions.Tests という名前を付けます。 既定のテスト ファイルを削除します。
  5. NuGet を使用して、テスト アプリから Microsoft.AspNetCore.Mvc への参照を追加します
  6. Functions.Tests アプリから Functions アプリを参照します。

これでプロジェクトが作成されたため、自動テストの実行に使用するクラスを作成できます。

2. テスト クラスの作成

各関数は、ILogger のインスタンスを取得して、メッセージ ログを処理します。 テストによっては、メッセージをログに記録しないことも、ログの実装方法に対する懸念がないこともあります。 その他のテストは、テストを渡すかどうかを判断するために、ログに記録されたメッセージを評価する必要があります。

  1. テストの間に評価するメッセージの内部リストを保持する ListLogger という名前のクラスを作成します。 必要な ILogger インターフェイスを実装するには、クラスにスコープが必要です。 次のクラスでは、ListLogger クラスに渡すテスト ケースのスコープがモックされます。

  2. Functions.Tests プロジェクトに NullScope.cs という名前の新しいクラスを作成し、次のコードを追加します。

    using System;
    
    namespace Functions.Tests
    {
        public class NullScope : IDisposable
        {
            public static NullScope Instance { get; } = new NullScope();
    
            private NullScope() { }
    
            public void Dispose() { }
        }
    }
    
  3. Functions.Tests プロジェクトに ListLogger.cs という名前のクラスを作成し、次のコードを追加します。

    using Microsoft.Extensions.Logging;
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Functions.Tests
    {
        public class ListLogger : ILogger
        {
            public IList<string> Logs;
    
            public IDisposable BeginScope<TState>(TState state) => NullScope.Instance;
    
            public bool IsEnabled(LogLevel logLevel) => false;
    
            public ListLogger()
            {
                this.Logs = new List<string>();
            }
    
            public void Log<TState>(LogLevel logLevel,
                                    EventId eventId,
                                    TState state,
                                    Exception exception,
                                    Func<TState, Exception, string> formatter)
            {
                string message = formatter(state, exception);
                this.Logs.Add(message);
            }
        }
    }
    

    ListLogger クラスは、ILogger インターフェイスによって縮小される次のメンバーを実装します。

    • BeginScope:スコープがログにコンテキストを追加します。 この場合、テストで NullScope クラスの静的インスタンスをポイントするだけで、テストを機能させることができます。

    • IsEnabled:既定の値 false が指定されます。

    • Log:このメソッドは、指定された formatter 関数を使用してメッセージの書式を設定してから、結果のテキストを Logs コレクションに追加します。

    Logs コレクションは List<string> のインスタンスであり、コンストラクターで初期化されます。

  4. Functions.Tests プロジェクトに LoggerTypes.cs という名前のコード ファイルを作成し、次のコードを追加します。

    namespace Functions.Tests
    {
        public enum LoggerTypes
        {
            Null,
            List
        }
    }
    

    この列挙型は、テストで使用されるロガーの種類を指定します。

  5. Functions.Tests プロジェクトに TestFactory.cs という名前のクラスを作成し、次のコードを追加します。

    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Http.Internal;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Logging.Abstractions;
    using Microsoft.Extensions.Primitives;
    using System.Collections.Generic;
    
    namespace Functions.Tests
    {
        public class TestFactory
        {
            public static IEnumerable<object[]> Data()
            {
                return new List<object[]>
                {
                    new object[] { "name", "Bill" },
                    new object[] { "name", "Paul" },
                    new object[] { "name", "Steve" }
    
                };
            }
    
            private static Dictionary<string, StringValues> CreateDictionary(string key, string value)
            {
                var qs = new Dictionary<string, StringValues>
                {
                    { key, value }
                };
                return qs;
            }
    
            public static HttpRequest CreateHttpRequest(string queryStringKey, string queryStringValue)
            {
                var context = new DefaultHttpContext();
                var request = context.Request;
                request.Query = new QueryCollection(CreateDictionary(queryStringKey, queryStringValue));
                return request;
            }
    
            public static ILogger CreateLogger(LoggerTypes type = LoggerTypes.Null)
            {
                ILogger logger;
    
                if (type == LoggerTypes.List)
                {
                    logger = new ListLogger();
                }
                else
                {
                    logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
                }
    
                return logger;
            }
        }
    }
    

    TestFactory クラスは、次のメンバーを実装します。

    • Data:このプロパティは、サンプル データの IEnumerable コレクションを返します。 キー値のペアは、クエリ文字列に渡される値を表します。

    • CreateDictionary:このメソッドは、キー/値ペアを引数として受け取り、クエリ文字列値を表す QueryCollection を作成するために使用する新しい Dictionary を返します。

    • CreateHttpRequest:このメソッドは、指定されたクエリ文字列パラメーターで初期化される HTTP 要求を作成します。

    • CreateLogger:このメソッドは、ロガーの種類に応じて、テストに使用されるロガー クラスを返します。 ListLogger は、テストで評価に使用できるログ記録されたメッセージを追跡します。

  6. Functions.Tests プロジェクトに FunctionsTests.cs という名前のクラスを作成し、次のコードを追加します。

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Logging;
    using Xunit;
    
    namespace Functions.Tests
    {
        public class FunctionsTests
        {
            private readonly ILogger logger = TestFactory.CreateLogger();
    
            [Fact]
            public async void Http_trigger_should_return_known_string()
            {
                var request = TestFactory.CreateHttpRequest("name", "Bill");
                var response = (OkObjectResult)await MyHttpTrigger.Run(request, logger);
                Assert.Equal("Hello, Bill. This HTTP triggered function executed successfully.", response.Value);
            }
    
            [Theory]
            [MemberData(nameof(TestFactory.Data), MemberType = typeof(TestFactory))]
            public async void Http_trigger_should_return_known_string_from_member_data(string queryStringKey, string queryStringValue)
            {
                var request = TestFactory.CreateHttpRequest(queryStringKey, queryStringValue);
                var response = (OkObjectResult)await MyHttpTrigger.Run(request, logger);
                Assert.Equal($"Hello, {queryStringValue}. This HTTP triggered function executed successfully.", response.Value);
            }
    
            [Fact]
            public void Timer_should_log_message()
            {
                var logger = (ListLogger)TestFactory.CreateLogger(LoggerTypes.List);
                new MyTimerTrigger().Run(null, logger);
                var msg = logger.Logs[0];
                Assert.Contains("C# Timer trigger function executed at", msg);
            }
        }
    }
    

    このクラスで実装されるメンバーは次のとおりです。

    • Http_trigger_should_return_known_string:このテストは、HTTP 関数へのクエリ文字列値 name=Bill を含む要求を作成し、予期された応答が返されることを確認します。

    • Http_trigger_should_return_string_from_member_data:このテストは、xUnit 属性を使用して、HTTP 関数にサンプル データを提供します。

    • Timer_should_log_message: このテストは、ListLogger のインスタンスを作成してタイマー関数に渡します。 関数が実行されると、予期されたメッセージが存在することを確認するためにログがチェックされます。

  7. テスト内でアプリケーションの設定にアクセスするには、モックされた環境変数の値を持つ IConfiguration インスタンスを関数に挿入できます。

3. テストの実行

テストを実行するには、テスト エクスプローラーに移動し、[すべてのテストをビューで実行] を選択します。

Visual Studio で C# を使って Azure Functions をテストする

4. テストのデバッグ

テストをデバッグするには、テストにブレークポイントを設定し、テスト エクスプローラーに移動して、[実行]> [前回の実行をデバッグする] の順に選択します。

次のステップ

Azure Functions Core Tools の詳細については、「Azure Functions Core Tools の操作」を参照してください。