Azure Logic Apps の Standard ワークフローから .NET Framework コードを作成して実行する

適用対象: Azure Logic Apps (Standard)

Standard ロジック アプリ ワークフローから .NET Framework コードを作成して実行する必要がある統合ソリューションでは、Azure Logic Apps (Standard) 拡張機能を含む Visual Studio Code を使用できます。 この拡張機能は、次の機能と利点を備えています。

  • 非常に困難な統合の問題を解決する柔軟性と制御性を備えた関数を作ることにより独自のコードを生成します。
  • Visual Studio Code で、コードをローカルでデバッグします。 同じデバッグ セッションでコードとワークフローをステップ実行します。
  • コードをワークフローと共にデプロイします。 他のサービス プランは必要ありません。
  • BizTalk Server の移行シナリオをサポートして、カスタムの .NET Framework への投資をオンプレミスからクラウドにリフトアンドシフトできるようにします。

独自のコードを記述する機能を使用して、次のようなシナリオを実現できます。

  • カスタム ビジネス ロジックの実装
  • 受信メッセージから情報を抽出するためのカスタム解析
  • データ検証と単純な変換
  • API など、別のシステムへの送信メッセージのメッセージ形成
  • 計算

この機能は、次のようなシナリオには適していません:

  • 実行時間が 10 分を超えるプロセス
  • 大規模なメッセージとデータの変換
  • 複雑なバッチ処理とバッチ解除のシナリオ
  • ストリーミングを実装する BizTalk Server パイプライン コンポーネント

Azure Logic Apps の制限の詳細については、Azure Logic Apps の制限と構成に関する記事を参照してください。

前提条件

  • Azure アカウントとサブスクリプション。 サブスクリプションをお持ちでない場合には、無料の Azure アカウントにサインアップしてください。

  • Azure Logic Apps (Standard) 拡張機能を含む Visual Studio Code。 これらの要件を満たすには、Visual Studio Code を使用してシングルテナント Azure Logic Apps で Standard ワークフローを作成するための前提条件を参照してください。

    • カスタム関数機能は現在、Windows オペレーティング システムで実行されている Visual Studio Code でのみ使用できます。

    • このカスタム関数機能は現在、.NET Framework 4.7.2 アセンブリの呼び出しにのみ対応しています。

  • コード プロジェクトの作成に使用するローカル フォルダー

制限事項

Azure portal では現在カスタム関数の作成はできません。 ただし、Visual Studio Code から Azure に関数を展開した後であれば、Azure portal 向けとして「作成したコードをワークフローからコールする」の手順に従ってください。 このロジック アプリ内のローカル関数を呼び出す という名前の組み込みアクションを使って、自身が展開したカスタム関数を選んで、作成したコードを実行させることができます。 ワークフロー内の後続のアクションは、他のワークフローと同様に、これらの関数の出力を参照できます。 組み込みアクションの実行履歴、入力、出力が表示されます。

コード プロジェクトを作成する

Visual Studio Code 用の最新の Azure Logic Apps (Standard) 拡張機能には、ワークフローを使用して独自のコードを記述、デバッグ、デプロイするためのエクスペリエンスを合理化する、コード プロジェクト テンプレートが含まれています。 このプロジェクト テンプレートを使用して、ワークスペース ファイルと 2 つのサンプル プロジェクト (1 つはコードを記述するプロジェクト、もう 1 つはワークフローを作成するプロジェクト) を作成します。

Note

コードとワークフローの両方に同じプロジェクト フォルダーを使用することはできません。

  1. Visual Studio Code を開きます。 アクティビティ バーの [Azure] アイコンを選択します。 (キーボード: Shift + Alt + A)

  2. 開いたAzure ウィンドウの [ワークスペース] セクション ツール バーで、[Azure Logic Apps] メニューから、[新しいプロジェクトの作成] を選択します。

    Screenshot shows Visual Studio Code, Azure window, Workspace section toolbar, and selected option for Create new logic app workspace.

  3. 「フォルダー選択」 ボックスで、プロジェクト用に作成したローカル フォルダーを見つけて選択します。

  4. 「新しいロジック アプリ ワークスペースを作成する」 プロンプト ボックスが表示されたら、ワークスペースに付ける名前を入力します:

    Screenshot shows Visual Studio Code with prompt to enter workspace name.

    この例では MyLogicAppWorkspace とします。

  5. 「ロジック アプリ ワークスペースのプロジェクト テンプレートを選択する」 プロンプト ボックスが表示されたら、「カスタム コード プロジェクトで使用するロジック アプリ」 を選択します。

    Screenshot shows Visual Studio Code with prompt to select project template for logic app workspace.

  6. 後続のプロンプトに従って、次の例の値を指定します:

    項目 値の例
    関数プロジェクトの関数名 WeatherForecast
    関数プロジェクトの名前空間名 Contoso.Enterprise
    ワークフロー テンプレート:
    - ステートフル ワークフロー
    - ステートレス ワークフロー
    ステートフル ワークフロー
    ワークフロー名 MyWorkflow
  7. [Open in current window] (現在のウィンドウで開く) を選択します。

    この手順を完了すると、Visual Studio Code でワークスペースが作成されます。例として、既定では、関数プロジェクトとロジック アプリ プロジェクトが含まれます:

    Screenshot shows Visual Studio Code with created workspace.

    ノード 説明
    <ワークスペース名> 関数プロジェクトとロジック アプリ ワークフロー プロジェクトの両方が含まれます。
    関数 関数プロジェクトの成果物が含まれます。 たとえば、<関数名>.cs ファイルは、コードを作成できるコード ファイルです。
    ロジック アプリ 空のワークフローなど、ロジック アプリ プロジェクトの成果物が含まれます。

コードを記述する

  1. ワークスペースで、[関数] ノードを展開します (まだ展開されていない場合)。

  2. <関数名>.cs ファイルを開きます。この例の場合 WeatherForecast.cs となります。

    既定では、このファイルには、次のコード要素を含むサンプル コードと、前に指定した値の例が必要に応じて含まれています。

    • 名前空間名
    • クラス名
    • 関数名
    • 関数のパラメーター
    • の戻り値の型 :
    • 複合型

    次の例は、完全なサンプル コードを示しています。

    //------------------------------------------------------------
    // Copyright (c) Microsoft Corporation. All rights reserved.
    //------------------------------------------------------------
    
    namespace Contoso.Enterprise
    {
        using System;
        using System.Collections.Generic;
        using System.Threading.Tasks;
        using Microsoft.Azure.Functions.Extensions.Workflows;
        using Microsoft.Azure.WebJobs;
        using Microsoft.Extensions.Logging;
    
        /// <summary>
        /// Represents the WeatherForecast flow invoked function.
        /// </summary>
        public class WeatherForecast
        {
    
            private readonly ILogger<WeatherForecast> logger;
    
            public WeatherForecast(ILoggerFactory loggerFactory)
            {
                logger = loggerFactory.CreateLogger<WeatherForecast>();
            }
    
            /// <summary>
            /// Executes the logic app workflow.
            /// </summary>
            /// <param name="zipCode">The zip code.</param>
            /// <param name="temperatureScale">The temperature scale (e.g., Celsius or Fahrenheit).</param>
            [FunctionName("WeatherForecast")]
            public Task<Weather> Run([WorkflowActionTrigger] int zipCode, string temperatureScale)
            {
    
                this.logger.LogInformation("Starting WeatherForecast with Zip Code: " + zipCode + " and Scale: " + temperatureScale);
    
                // Generate random temperature within a range based on the temperature scale
                Random rnd = new Random();
                var currentTemp = temperatureScale == "Celsius" ? rnd.Next(1, 30) : rnd.Next(40, 90);
                var lowTemp = currentTemp - 10;
                var highTemp = currentTemp + 10;
    
                // Create a Weather object with the temperature information
                var weather = new Weather()
                {
                    ZipCode = zipCode,
                    CurrentWeather = $"The current weather is {currentTemp} {temperatureScale}",
                    DayLow = $"The low for the day is {lowTemp} {temperatureScale}",
                    DayHigh = $"The high for the day is {highTemp} {temperatureScale}"
                };
    
                return Task.FromResult(weather);
            }
    
            /// <summary>
            /// Represents the weather information for WeatherForecast.
            /// </summary>
            public class Weather
            {
                /// <summary>
                /// Gets or sets the zip code.
                /// </summary>
                public int ZipCode { get; set; }
    
                /// <summary>
                /// Gets or sets the current weather.
                /// </summary>
                public string CurrentWeather { get; set; }
    
                /// <summary>
                /// Gets or sets the low temperature for the day.
                /// </summary>
                public string DayLow { get; set; }
    
                /// <summary>
                /// Gets or sets the high temperature for the day.
                /// </summary>
                public string DayHigh { get; set; }
            }
        }
    }
    

    この関数定義には、作業を開始するために使用できる既定の Run メソッドが含まれています。 この Run メソッドのサンプルは、複雑な .NET 型を含む、さまざまな入力と出力を渡す機能など、カスタム関数機能で使用できる機能の一部を示します。

    また、<関数名>.cs ファイルは ILogger インターフェイスを持ち、Application Insights リソースへのイベントのロギングのサポートを提供します。 例えば、Application Insights にトレース情報を送信し、その情報をワークフローからのトレース情報とともに格納できます:

    private readonly ILogger<WeatherForecast> logger;
    
    public WeatherForecast(ILoggerFactory loggerFactory)
    {
        logger = loggerFactory.CreateLogger<WeatherForecast>();
    }
    
    [FunctionName("WeatherForecast")]
    public Task<Weather> Run([WorkflowActionTrigger] int zipCode, string temperatureScale)
    {
    
        this.logger.LogInformation("Starting WeatherForecast with Zip Code: " + zipCode + " and Scale: " + temperatureScale);
    
        <...>
    
    }
    
  3. サンプルの関数コードを独自の関数コードに置き換え、ご自身のシナリオに合わせて既定の Run メソッドを編集します。 または、[FunctionName("<*function-name*>")] 宣言を含む関数をコピーし、関数の名前を一意の名前に変更することもできます。 その後、名前を変更した関数を、ニーズに合わせて編集できます。

この例では、変更を加えずにサンプル コードをそのまま使用します。

コードをコンパイルしてビルドする

コードの記述が完了したら、コンパイルしてビルド エラーが存在しないことを確認します。 関数プロジェクトにはビルド タスクが自動的に含まれます。これにより、コードがコンパイルされ、ロジック アプリ プロジェクト内の lib\custom フォルダーに追加されます。ワークフローでは、実行するカスタム関数をここで検索します。 これらのタスクにより、アセンブリが lib\custom\net472 フォルダーに配置されます。

  1. Visual Studio Code で、[Terminal] (ターミナル) メニューから [New Terminal] (新しいターミナル) を選択します。

  2. 表示された作業ディレクトリの一覧から、新しいターミナルの現在の作業ディレクトリとして [関数] を選択します。

    Screenshot shows Visual Studio Code, prompt for current working directory, and selected Functions directory.

    Visual Studio Code で、コマンド プロンプトが表示されたターミナル ウィンドウが開きます。

  3. [Terminal] (ターミナル) ウィンドウのコマンド プロンプトに、「dotnet restore」と入力します。

    Visual Studio Code では、プロジェクトを分析して、それらが最新かどうかを判断します。

    Screenshot shows Visual Studio Code, Terminal window, and completed dotnet restore command.

  4. コマンド プロンプトがもう一度表示されたら、「dotnet build」と入力します。 または、[ターミナル] メニューの [タスクの実行] を選択します。 タスクの一覧から [ビルド (関数)] を選択します。

    ビルドが成功すると、[Terminal] (ターミナル) ウィンドウに [ビルドが正常に終了しました] と報告されます。

  5. ロジック アプリ プロジェクトに次の項目が存在することを確認します。

    • ワークスペースで、次のフォルダーを展開します: LogicApp>lib\custom>net472net472 という名前のサブフォルダーに、<function-name>.dll という名前のファイルを含む、コードの実行に必要な複数のアセンブリ (DLL) ファイルが含まれていることを確認します。

    • ワークスペースで、次のフォルダーを展開します: LogicApp>lib\custom><function-name><function-name> という名前のサブフォルダーに、作成した関数コードに関するメタデータを含む function.json ファイルが含まれていることを確認します。 ワークフロー デザイナーは、このファイルを使用して、コードの呼び出し時に必要な入力と出力を判断します。

    次の例は、ロジック アプリ プロジェクトで生成されたアセンブリとその他のファイルの例を示しています。

    Screenshot shows Visual Studio Code and logic app workspace with function project and logic app project, now with the generated assemblies and other required files.

ワークフローからコードを呼び出す

コードがコンパイルされたこと、およびロジック アプリ プロジェクトにコードの実行に必要なファイルが含まれていることを確認したら、ロジック アプリ プロジェクトに含まれている既定のワークフローを開きます。

  1. ワークスペースの [LogicApp] で、<ワークフロー名> ノードを展開し、workflow.json のショートカット メニューを開き、[デザイナーを開く] を選択します。

    開いたワークフロー デザイナーに、ロジック アプリ プロジェクトに含まれる既定のワークフローが、次のトリガーおよびアクションと共に表示されます。

  2. [Call a local function in this logic app] (このロジック アプリのローカル関数の呼び出し) という名前のアクションを選択します。

    このアクションの情報ペインが右側に開きます。

    Screenshot shows Visual Studio Code, workflow designer, and default workflow with trigger and actions.

  3. [関数名] パラメーターの値が、実行する関数に設定されていることを確認します。 関数で使用するその他のパラメーター値を確認または変更します。

コードとワークフローをデバッグする

  1. Azurite ストレージ エミュレーターを起動するには、次の手順を 3 回 (次の各 Azure Storage サービスに対して 1 回ずつ) 繰り返します。

    • Azure BLOB サービス
    • Azure Queue サービス
    • Azure テーブル サービス
    1. Visual Studio Code の [表示] メニューから [コマンド パレット] を選びます。

    2. 表示されたプロンプトで、[Azurite: Start Blob Service] (Azurite: BLOB サービスの開始) を見つけて選択します。

    3. 表示された作業ディレクトリの一覧から、[LogicApp] を選択します。

    4. [Azurite: Start Queue Service] (Azurite: Queue サービスの開始)[Azurite: Start Table Service] (Azurite: Table サービスの開始) に対して、これらの手順を繰り返します。

    画面の下部にある Visual Studio Code タスク バーに 3 つのストレージ サービスが実行されていることが示されたら、操作は成功です。次に例を示します。

    Screenshot shows Visual Studio Code taskbar with Azure Blob Service, Azure Queue Service, and Azure Table Service running.

  2. Visual Studio Code のアクティビティ バーで、[Run and Debug] (実行とデバッグ) を選択します。 (キーボード: Ctrl + Shift + D)

    Screenshot shows Visual Studio Code Activity Bar with Run and Debug selected.

  3. [Run and Debug] (実行とデバッグ) の一覧で、[Attach to logic app (LogicApp)] (ロジック アプリ (LogicApp) にアタッチ) を選択し (まだ選択されていない場合)、[再生] (緑色の矢印) を選択します。

    Screenshot shows Run and Debug list with Attach to logic app selected and Play button selected.

    [Terminal] (ターミナル) ウィンドウが開き、デバッグ プロセスが開始したことを示します。 [Debug Console] (デバッグ コンソール) ウィンドウが表示され、デバッグの状態が表示されます。 Visual Studio Code の下部にあるタスク バーがオレンジ色に変わり、.NET デバッガーが読み込まれたことを示します。

  4. [Run and Debug] (実行とデバッグ) の一覧で、[Attach to .NET Functions (Functions)] (.NET Functions (Functions) にアタッチ) を選択し、[再生] (緑色の矢印) を選択します。

    Screenshot shows Run and Debug list with Attach to NET Functions selected and Play button selected.

  5. ブレークポイントを設定するには、関数定義 (<関数名>.cs) またはワークフロー定義 (workflow.json) で、ブレークポイントが必要な行番号を見つけて、左側の列を選択します。次に例を示します。

    Screenshot shows Visual Studio Code and the open function code file with a breakpoint set for a line in code.

  6. ワークフローで要求トリガーを手動で実行するには、ワークフローの [概要] ページを開きます。

    1. ロジック アプリ プロジェクトから workflow.json ファイルのショートカット メニューを開き、[概要] を選択します。

      ワークフローの [概要] ページには、ワークフローを手動で開始する場合のために [トリガーの実行] ボタンが用意されています。 [Workflow Properties] (ワークフローのプロパティ)[コールバック URL] の値は、ワークフロー内の要求トリガーによって作成された呼び出し可能なエンドポイントの URL です。 この URL に要求を送信して、他のアプリ (他のロジック アプリ ワークフローなど) からワークフローをトリガーできます。

      Screenshot shows Visual Studio Code and workflow's Overview page opened.

  7. [概要] ページのツール バーで、[トリガーの実行] を選択します。

    ワークフローの実行が開始されると、デバッガーによって最初のブレークポイントがアクティブになります。

  8. [実行] メニューまたはデバッガーのツール バーで、デバッグ アクションを選択します。

    ワークフローの実行が完了すると、[概要] ページに、完了した実行とその実行に関する基本的な詳細が表示されます。

  9. ワークフロー実行の詳細を確認するには、完了した実行を選択します。 または、[実行時間] 列の横にある一覧から [Show run] (実行の表示) を選択します。

    Screenshot shows Visual Studio Code and finished workflow run.

コードのデプロイ

カスタム コードは、ロジック アプリ プロジェクトの展開と同じ方法で展開できます。 Visual Studio Code からデプロイする場合も、CI/CD DevOps プロセスを使用する場合も、デプロイする前に、コードをビルドしていること、およびすべての依存アセンブリがロジック アプリ プロジェクトの lib/custom/net472 フォルダーに存在することを確認してください。 詳細については、Visual Studio Code から Azure への Standard ワークフローのデプロイに関する記事を参照してください。

問題のトラブルシューティング

アクション情報ペインのエラー

ワークフロー デザイナーで、[Call a local function in this logic app] (このロジック アプリのローカル関数の呼び出し) という名前の組み込みアクションを選択すると、アクションの情報ペインに次のメッセージが表示されます。

Failed to retrieve dynamic inputs. Error details:

このシナリオでは、ロジック アプリ プロジェクトを調べて、LogicApp\lib\custom フォルダーが空かどうかを確認します。 空の場合は、Terminal (ターミナル) メニューの タスクの実行>build Functions (関数のビルド) を選択します。

No process with the specified name is currently running (指定された名前のプロセスは現在実行されていません)

ワークフローの実行時にこのエラー メッセージが表示される場合、デバッガー プロセスがロジック アプリではなく .NET Functions にアタッチされている可能性があります。

この問題を修正するには、[Run and Debug] (実行とデバッグ) の一覧で、[Attach to logic app (LogicApp)] (ロジック アプリ (LogicApp) にアタッチ) を選択し、[再生] (緑色の三角) を選択します。

パッケージが正しくインポートされない

出力ウィンドウに次のメッセージのようなエラーが表示される場合は、.NET 6.0 がインストールされていることを確認します。 このバージョンがインストールされている場合は、アンインストールしてから再インストールしてみてください。

C:\Users\yourUserName\.nuget\packages\microsoft.net.sdk.functions\4.2.0\build\Microsoft.NET.Sdk.Functions.targets(83,5): warning : The ExtensionsMetadataGenerator package was not imported correctly. Are you missing 'C:\Users\yourUserName\.nuget\packages\microsoft.azure.webjobs.script.extensionsmetadatagenerator\4.0.1\build\Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator.targets' or 'C:\Users\yourUserName\.nuget\packages\microsoft.azure.webjobs.script.extensionsmetadatagenerator\4.0.1\build\Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator.props'? [C:\Desktop\...\custom-code-project\MyLogicAppWorkspace\Function\WeatherForecast.csproj] WeatherForecast -> C:\Desktop\...\custom-code-project\MyLogicAppWorkspace\Function\\bin\Debug\net472\WeatherForecast.dll C:\Users\yourUserName\.nuget\packages\microsoft.net.sdk.functions\4.2.0\build\Microsoft.NET.Sdk.Functions.Build.targets(32,5): error : It was not possible to find any compatible framework version [C:\Desktop\...\custom-code-project\MyLogicAppWorkspace\Function\WeatherForecast.csproj] C:\Users\yourUserName\.nuget\packages\microsoft.net.sdk.functions\4.2.0\build\Microsoft.NET.Sdk.Functions.Build.targets(32,5): error : The specified framework 'Microsoft.NETCore.App', version '6.0.0' was not found. [C:\Desktop\...\custom-code-project\MyLogicAppWorkspace\Function\WeatherForecast.csproj] C:\Users\yourUserName\.nuget\packages\microsoft.net.sdk.functions\4.2.0\build\Microsoft.NET.Sdk.Functions.Build.targets(32,5): error : - Check application dependencies and target a framework version installed at: [C:\Desktop\...\custom-code-project\MyLogicAppWorkspace\Function\WeatherForecast.csproj]

ビルドが失敗する

関数に変数が含まれていない場合に、コードをビルドすると、出力ウィンドウに次のエラー メッセージが表示されることがあります。

C:\Users\yourUserName\...\custom-code-project\Function\func.cs (24,64): error CS1031: Type expected [C:\Users\yourUserName\...\custom-code-project\Function\func.csproj]
C:\Users\yourUserName\...\custom-code-project\Function\func.cs (24,64): error CS1001: Identifier expected [C:\Users\yourUserName\...\custom-code-project\Function\func.csproj]

Build FAILED.

C:\Users\yourUserName\...\custom-code-project\Function\func.cs (24,64): error CS1031: Type expected [C:\Users\yourUserName\...\custom-code-project\Function\func.csproj]
C:\Users\yourUserName\...\custom-code-project\Function\func.cs (24,64): error CS1001: Identifier expected [C:\Users\yourUserName\...\custom-code-project\Function\func.csproj]

0 Warning(s)
2 Error(s)

この問題を解決するには、コードの Run メソッドに次のパラメーターを追加します。

string parameter1 = null

次の例は、Run メソッドのシグネチャがどのように表示されるかを示しています。

public static Task<Weather> Run([WorkflowActionTrigger] int zipCode, string temperatureScale, string parameter1 = null)

次の手順

Visual Studio Code を使って Standard ワークフローを作成する