Azure Logic Apps の Standard ワークフローから .NET コードを作成して実行する
適用対象: Azure Logic Apps (Standard)
Standard ロジック アプリ ワークフローから .NET コードを作成して実行する必要がある統合ソリューションでは、Visual Studio Code と Azure Logic Apps (Standard) 拡張機能を使用できます。 この拡張機能は、次の機能と利点を備えています。
- 非常に困難な統合の問題を解決する柔軟性と制御性を備えた関数を作ることにより独自のコードを生成します。
- Visual Studio Code で、コードをローカルでデバッグします。 同じデバッグ セッションでコードとワークフローをステップ実行します。
- コードをワークフローと共にデプロイします。 他のサービス プランは必要ありません。
- BizTalk Server の移行シナリオをサポートして、カスタムの .NET への投資をオンプレミスからクラウドにリフトアンドシフトできるようにします。
独自のコードを記述する機能を使用して、次のようなシナリオを実現できます。
- カスタム ビジネス ロジックの実装
- 受信メッセージから情報を抽出するためのカスタム解析
- データ検証と単純な変換
- API など、別のシステムへの送信メッセージのメッセージ形成
- 計算
この機能は、次のようなシナリオには適していません:
- 実行時間が 10 分を超えるプロセス
- 大規模なメッセージとデータの変換
- 複雑なバッチ処理とバッチ解除のシナリオ
- ストリーミングを実装する BizTalk Server パイプライン コンポーネント
Azure Logic Apps の制限の詳細については、Azure Logic Apps の制限と構成に関する記事を参照してください。
前提条件
Azure アカウントとサブスクリプション。 サブスクリプションをお持ちでない場合には、無料の Azure アカウントにサインアップしてください。
最新の Visual Studio Code と Azure Logic Apps (Standard) 拡張機能。 これらの要件を満たすには、Visual Studio Code を使用してシングルテナント Azure Logic Apps で Standard ワークフローを作成するための前提条件を参照してください。
カスタム関数機能は現在、Windows オペレーティング システムで実行されている Visual Studio Code でのみ使用できます。
カスタム関数機能では、現在、Azure でホストされるロジック アプリ ワークフローに対する .NET Framework と .NET 8 の呼び出しがサポートされています。
コード プロジェクトの作成に使用するローカル フォルダー
制限事項
Azure portal では現在カスタム関数の作成はできません。 ただし、Visual Studio Code から Azure に関数を展開した後であれば、Azure portal 向けとして「作成したコードをワークフローからコールする」の手順に従ってください。 このロジック アプリ内のローカル関数を呼び出す という名前の組み込みアクションを使って、自身が展開したカスタム関数を選んで、作成したコードを実行させることができます。 ワークフロー内の後続のアクションは、他のワークフローと同様に、これらの関数の出力を参照できます。 組み込みアクションの実行履歴、入力、出力が表示されます。
カスタム関数は、分離ワーカーを使用してロジック アプリ ワークフロー内のコードを呼び出します。 独自の関数コードとワーカーの間でパッケージ参照が競合しないようにするには、ワーカーによって参照されているのと同じパッケージ バージョンを使用します。 ワーカーによって参照される完全なパッケージの一覧とバージョンについては、「ワーカーとパッケージの依存関係」を参照してください。
コード プロジェクトを作成する
Visual Studio Code 用の最新の Azure Logic Apps (Standard) 拡張機能には、ワークフローを使用して独自のコードを記述、デバッグ、デプロイするためのエクスペリエンスを合理化する、コード プロジェクト テンプレートが含まれています。 このプロジェクト テンプレートを使用して、ワークスペース ファイルと 2 つのサンプル プロジェクト (1 つはコードを記述するプロジェクト、もう 1 つはワークフローを作成するプロジェクト) を作成します。
Note
コードとワークフローの両方に同じプロジェクト フォルダーを使用することはできません。
Visual Studio Code を開きます。 アクティビティ バーの [Azure] アイコンを選択します。 (キーボード: Shift + Alt + A)
開いたAzure ウィンドウの [ワークスペース] セクション ツール バーで、[Azure Logic Apps] メニューから、[新しいプロジェクトの作成] を選択します。
「フォルダー選択」 ボックスで、プロジェクト用に作成したローカル フォルダーを見つけて選択します。
「新しいロジック アプリ ワークスペースを作成する」 プロンプト ボックスが表示されたら、ワークスペースに付ける名前を入力します:
この例では MyLogicAppWorkspace とします。
「ロジック アプリ ワークスペースのプロジェクト テンプレートを選択する」 プロンプト ボックスが表示されたら、「カスタム コード プロジェクトで使用するロジック アプリ」 を選択します。
Azure でホストされる Standard ロジック アプリ ワークフローの場合は、プロンプトに従って、.NET Framework または .NET 8 を選びます。
後続のプロンプトに従って、次の例の値を指定します:
項目 値の例 .NET 関数プロジェクトの関数名 WeatherForecast .NET 関数プロジェクトの名前空間名 Contoso.Enterprise ワークフロー テンプレート:
- ステートフル ワークフロー
- ステートレス ワークフローステートフル ワークフロー ワークフロー名 MyWorkflow [Open in current window] (現在のウィンドウで開く) を選択します。
このステップを終えると、Visual Studio Code によってワークスペースが作成されます。これには、たとえば、.NET 関数プロジェクトとロジック アプリ プロジェクトが既定で含まれます:
Node 説明 <ワークスペース名> .NET 関数プロジェクトとロジック アプリ ワークフロー プロジェクトの両方が含まれます。 関数 .NET 関数プロジェクトの成果物が含まれます。 たとえば、<関数名>.cs ファイルは、コードを作成できるコード ファイルです。 ロジック アプリ 空のワークフローなど、ロジック アプリ プロジェクトの成果物が含まれます。
コードを記述する
ワークスペースで、[関数] ノードを展開します (まだ展開されていない場合)。
<関数名>.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); <...> }
サンプルの関数コードを独自の関数コードに置き換え、ご自身のシナリオに合わせて既定の
Run
メソッドを編集します。 または、[FunctionName("<*function-name*>")]
宣言を含む関数をコピーし、関数の名前を一意の名前に変更することもできます。 その後、名前を変更した関数を、ニーズに合わせて編集できます。
この例では、変更を加えずにサンプル コードをそのまま使用します。
コードをコンパイルしてビルドする
コードの記述が完了したら、コンパイルしてビルド エラーが存在しないことを確認します。 .NET 関数プロジェクトにはビルド タスクが自動的に含まれ、これによりコードがコンパイルされて、ロジック アプリ プロジェクトの lib\custom フォルダーに追加されます。ワークフローは、実行するカスタム関数をここで検索します。 これらのタスクは、.NET のバージョンに基づいて、アセンブリを lib\custom\net472 または lib\custom\net8 フォルダーに配置します。
Visual Studio Code で、[Terminal] (ターミナル) メニューから [New Terminal] (新しいターミナル) を選択します。
表示された作業ディレクトリの一覧から、新しいターミナルの現在の作業ディレクトリとして [関数] を選択します。
Visual Studio Code で、コマンド プロンプトが表示されたターミナル ウィンドウが開きます。
[Terminal] (ターミナル) ウィンドウのコマンド プロンプトに、「dotnet restore」と入力します。
Visual Studio Code では、プロジェクトを分析して、それらが最新かどうかを判断します。
コマンド プロンプトがもう一度表示されたら、「dotnet build」と入力します。 または、[ターミナル] メニューの [タスクの実行] を選択します。 タスクの一覧から [ビルド (関数)] を選択します。
ビルドが成功すると、[Terminal] (ターミナル) ウィンドウに [ビルドが正常に終了しました] と報告されます。
ロジック アプリ プロジェクトに次の項目が存在することを確認します。
ワークスペースで、.NET のバージョンに基づいて、LogicApp>lib\custom>net472 または net8 フォルダーを展開します。 それぞれ、net472 または net8 という名前のサブフォルダーに、<function-name>.dll という名前のファイルを含む、コードの実行に必要なアセンブリ (DLL) ファイルが含まれていることを確認します。
ワークスペースで、次のフォルダーを展開します: LogicApp>lib\custom><function-name>。 <function-name> という名前のサブフォルダーに、作成した関数コードに関するメタデータを含む function.json ファイルが含まれていることを確認します。 ワークフロー デザイナーは、このファイルを使用して、コードの呼び出し時に必要な入力と出力を判断します。
次の例は、ロジック アプリ プロジェクトで生成されたアセンブリとその他のファイルの例を示しています。
ワークフローからコードを呼び出す
コードがコンパイルされたこと、およびロジック アプリ プロジェクトにコードの実行に必要なファイルが含まれていることを確認したら、ロジック アプリ プロジェクトに含まれている既定のワークフローを開きます。
ワークスペースの [LogicApp] で、<ワークフロー名> ノードを展開し、workflow.json のショートカット メニューを開き、[デザイナーを開く] を選択します。
開いたワークフロー デザイナーに、ロジック アプリ プロジェクトに含まれる既定のワークフローが、次のトリガーおよびアクションと共に表示されます。
- [HTTP 要求の受信時] という名前の組み込みの要求トリガー
- [Call a local function in this logic app] (このロジック アプリのローカル関数の呼び出し) という名前の組み込みアクション
- [応答] という名前の組み込みの応答アクション。要求トリガーを使用するときにのみ呼び出し元に返信する場合に使用します
[Call a local function in this logic app] (このロジック アプリのローカル関数の呼び出し) という名前のアクションを選択します。
このアクションの情報ペインが右側に開きます。
[関数名] パラメーターの値が、実行する関数に設定されていることを確認します。 関数で使用するその他のパラメーター値を確認または変更します。
コードとワークフローをデバッグする
Azurite ストレージ エミュレーターを起動するには、次の手順を 3 回 (次の各 Azure Storage サービスに対して 1 回ずつ) 繰り返します。
- Azure BLOB サービス
- Azure Queue サービス
- Azure テーブル サービス
Visual Studio Code の [表示] メニューから [コマンド パレット] を選びます。
表示されたプロンプトで、[Azurite: Start Blob Service] (Azurite: BLOB サービスの開始) を見つけて選択します。
表示された作業ディレクトリの一覧から、[LogicApp] を選択します。
[Azurite: Start Queue Service] (Azurite: Queue サービスの開始) と [Azurite: Start Table Service] (Azurite: Table サービスの開始) に対して、これらの手順を繰り返します。
画面の下部にある Visual Studio Code タスク バーに 3 つのストレージ サービスが実行されていることが示されたら、操作は成功です。次に例を示します。
次の手順のようにして、デバッガーをロジック アプリ プロジェクトにアタッチします。
Visual Studio Code のアクティビティ バーで、[Run and Debug] (実行とデバッグ) を選択します。 (キーボード: Ctrl + Shift + D)
[Run and Debug] (実行とデバッグ) の一覧で、[Attach to logic app (LogicApp)] (ロジック アプリ (LogicApp) にアタッチ) を選択し (まだ選択されていない場合)、[再生] (緑色の矢印) を選択します。
[Terminal] (ターミナル) ウィンドウが開き、デバッグ プロセスが開始したことを示します。 [Debug Console] (デバッグ コンソール) ウィンドウが表示され、デバッグの状態が表示されます。 Visual Studio Code の下部にあるタスク バーがオレンジ色に変わり、.NET デバッガーが読み込まれたことを示します。
コードに基づき、次の手順のようにして、デバッガーを .NET 関数プロジェクトにアタッチします。
.NET 8 プロジェクト
Visual Studio Code の [表示] メニューから [コマンド パレット] を選びます。
コマンド パレットから、[Debug: .NET 5+ または .NET Core プロセスにアタッチ] を見つけて選びます。
一覧から、dotnet.exe プロセスを見つけて選びます。 複数の dotnet.exe プロセスが存在する場合は、次のパスを持つプロセスを選びます。
<ドライブ名>:\Users<ユーザー名>.azure-functions-core-tools\Functions\ExtensionBundles\Microsoft.Azure.Functions.ExtensionBundle.Workflows<extension-bundle-version>\CustomCodeNetFxWorker\net8\Microsoft.Azure.Workflows.Functions.CustomCodeNetFxWorker.dll
.NET Framework プロジェクト
[実行とデバッグ] の一覧で、[.NET 関数にアタッチ (関数)] を選び (まだ選ばれていない場合)、[再生] (緑色の矢印) を選びます。
ブレークポイントを設定するには、関数定義 (<関数名>.cs) またはワークフロー定義 (workflow.json) で、ブレークポイントが必要な行番号を見つけて、左側の列を選択します。次に例を示します。
ワークフローで要求トリガーを手動で実行するには、ワークフローの [概要] ページを開きます。
ロジック アプリ プロジェクトから workflow.json ファイルのショートカット メニューを開き、[概要] を選択します。
ワークフローの [概要] ページには、ワークフローを手動で開始する場合のために [トリガーの実行] ボタンが用意されています。 [Workflow Properties] (ワークフローのプロパティ) の [コールバック URL] の値は、ワークフロー内の要求トリガーによって作成された呼び出し可能なエンドポイントの URL です。 この URL に要求を送信して、他のアプリ (他のロジック アプリ ワークフローなど) からワークフローをトリガーできます。
[概要] ページのツール バーで、[トリガーの実行] を選択します。
ワークフローの実行が開始されると、デバッガーによって最初のブレークポイントがアクティブになります。
[実行] メニューまたはデバッガーのツール バーで、デバッグ アクションを選択します。
ワークフローの実行が完了すると、[概要] ページに、完了した実行とその実行に関する基本的な詳細が表示されます。
ワークフロー実行の詳細を確認するには、完了した実行を選択します。 または、[実行時間] 列の横にある一覧から [Show run] (実行の表示) を選択します。
コードのデプロイ
カスタム コードは、ロジック アプリ プロジェクトの展開と同じ方法で展開できます。 Visual Studio Code からデプロイする場合も、CI/CD DevOps プロセスを使う場合も、デプロイする前に、コードをビルドしていること、およびすべての依存アセンブリが次のロジック アプリ プロジェクト フォルダーに存在することを確認してます。
.NET 4.7.2: lib/custom/net472 フォルダー
.NET 8: lib/custom/net8 フォルダー
詳細については、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)