Skip to main content

dotnet-local-functions-logic-apps

Creates .NET local functions (custom code) for Azure Logic Apps Standard. Covers exact NuGet packages, namespaces, csproj, MSBuild targets, VS Code config, function.json, and workflow InvokeFunction patterns for both .NET 8 and .NET Framework 4.7.2.

Source facts

Repository
Azure/logicapps-migration-agent
Last source activity
March 27, 2026 at 10:38
Detected SKILL.md language
English
Stars
10
Forks
13

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
dotnet-local-functions-logic-apps
description
Creates .NET local functions (custom code) for Azure Logic Apps Standard. Covers exact NuGet packages, namespaces, csproj, MSBuild targets, VS Code config, function.json, and workflow InvokeFunction patterns for both .NET 8 and .NET Framework 4.7.2.
# Skill: Creating .NET Local Functions for Azure Logic Apps Standard > **Purpose**: This document is a definitive reference for AI agents generating .NET local functions (custom code) that run inside Azure Logic Apps Standard workflows. It contains the **exact files, folder structure, NuGet packages, MSBuild targets, VS Code configuration, and workflow invocation patterns** taken from verified working projects. Following this document precisely will produce a working project on the first attempt. > > **Two approaches are documented**: .NET Framework 4.7.2 (legacy, in-process) and .NET 8 (modern, recommended). Both use the same workspace layout pattern. Pick one based on your needs. --- ## Table of Contents <!-- TOC - using HTML anchors to avoid markdown link validation issues --> 1. <a href="#1-overview">Overview</a> 2. <a href="#2-architecture--workspace-layout-both-approaches">Architecture &amp; Workspace Layout (Both Approaches)</a> 3. <a href="#3-critical-nuget-package-information">Critical NuGet Package Information</a> 4. <a href="#4-approach-a--net-8-recommended">Approach A — .NET 8 (RECOMMENDED)</a> 5. <a href="#5-approach-b--net-framework-472-legacy">Approach B — .NET Framework 4.7.2 (Legacy)</a> 6. <a href="#6-shared-logic-app-project-files-both-approaches">Shared Logic App Project Files (Both Approaches)</a> 7. <a href="#7-calling-custom-code-from-workflowjson">Calling Custom Code from workflow.json</a> 8. <a href="#8-functionjson-reference">function.json Reference</a> 9. <a href="#9-building-and-running-locally">Building and Running Locally</a> 10. <a href="#10-supported-parameter--return-types">Supported Parameter &amp; Return Types</a> 11. <a href="#11-verification-checklists">Verification Checklists</a> 12. <a href="#12-troubleshooting-guide">Troubleshooting Guide</a> 13. <a href="#13-complete-working-examples">Complete Working Examples</a> 14. <a href="#14-quick-reference-card">Quick Reference Card</a> 15. <a href="#15-step-by-step-creation-guide-for-agents">Step-by-Step Creation Guide for Agents</a> --- ## 1. Overview Logic Apps Standard supports calling custom .NET code directly from workflows using the **"Call a local function in this logic app"** built-in action (`InvokeFunction` type). The .NET code runs alongside the Logic Apps runtime — no separate Azure Function hosting is needed. ### When to Use - Porting MuleSoft custom Java components, complex DataWeave logic, or MEL expressions to .NET - Custom business logic (calculations, transformations, validations) - XML/JSON document construction using System.Xml or System.Text.Json - Any scenario where built-in Logic Apps actions/expressions are insufficient ### When NOT to Use - Processes that take more than 10 minutes - Large message/data transformations (use Data Mapper instead) - Complex batching/debatching - MuleSoft streaming transformations or large payload processing ### Which Approach to Choose | Factor | .NET Framework 4.7.2 (`net472`) | .NET 8 (`net8`) | | ----------------------------- | --------------------------------------------- | --------------------------------------------- | | **Status** | Legacy — still works | **Recommended** — modern path | | **Worker model** | In-process (classic) | Isolated worker | | **Function attribute** | `[FunctionName("...")]` | `[Function("...")]` | | **Using for function attr** | `Microsoft.Azure.WebJobs` | `Microsoft.Azure.Functions.Worker` | | **Build output folder** | `lib/custom/net472/` | `lib/custom/net8/` | | **function.json Language** | `"net472"` | `"net8"` | | **VS Code customCodeRuntime** | `"clr"` | `"coreclr"` | | **Project layout** | **Sibling** `Functions/` and LogicApp folders | **Sibling** `Functions/` and LogicApp folders | | **Best for** | Quick ports of existing .NET Framework code | Production projects, CI/CD, new development | --- ## 2. Architecture & Workspace Layout (Both Approaches) > **CRITICAL**: Both .NET 8 and .NET 4.7.2 use the **same workspace layout pattern** — the Functions project and Logic App project are **sibling folders** with a `.code-workspace` file at the root. The Functions project is **NOT** nested inside the Logic App. ### 2.1 Complete Directory Structure ``` <workspace-root>/ ├── <workspace-name>.code-workspace ← VS Code workspace file │ ├── Functions/ ← .NET function project (sibling) │ ├── Functions.csproj ← Project file with MSBuild auto-deploy targets │ ├── <FunctionName>.cs ← One or more C# function files │ └── .vscode/ │ ├── extensions.json │ ├── settings.json │ └── tasks.json │ └── <logicapp-name>/ ← Logic Apps Standard project (sibling) ├── host.json ← Functions host configuration ├── local.settings.json ← Runtime settings (CRITICAL) ├── .funcignore ← Files to exclude from deployment ├── .gitignore ← Git ignore rules │ ├── .vscode/ │ ├── extensions.json │ ├── launch.json ← Debug configuration (CRITICAL: customCodeRuntime differs!) │ ├── settings.json │ └── tasks.json │ ├── lib/ │ └── custom/ ← Build outputs auto-copied here │ ├── <FunctionName>/ ← Contains function.json (auto-generated) │ │ └── function.json │ └── net8/ OR net472/ ← Contains DLLs (auto-copied by build) │ ├── Functions.dll │ ├── Functions.pdb │ └── (dependency DLLs) │ ├── <workflow-name>/ ← One or more workflow folders │ └── workflow.json │ └── workflow-designtime/ ← Design-time configuration ├── host.json └── local.settings.json ``` ### 2.2 Key Structural Rules 1. **Functions/ and LogicApp are siblings** — they sit next to each other under the workspace root 2. **The workspace file references both folders** — so VS Code opens them as a multi-root workspace 3. **Build auto-deploys** — MSBuild targets in the `.csproj` copy DLLs and `function.json` to `lib/custom/` 4. **`lib/custom/` is the bridge** — DLLs go in `lib/custom/net8/` or `lib/custom/net472/`, function metadata goes in `lib/custom/<FunctionName>/function.json` 5. **workflow-designtime/** is required — it enables the Logic Apps designer to discover custom functions --- ## 3. Critical NuGet Package Information ### ⚠️ THE #1 MISTAKE: Wrong Package Name | What you might guess | Exists on NuGet? | Correct? | | ------------------------------------------------ | ---------------- | -------- | | `Microsoft.Azure.Functions.Extensions.Workflows` | **NO** ❌ | ❌ | | `Microsoft.Azure.Workflows.WebJobs.Sdk` | **YES** ✅ | ✅ | **Why this is confusing**: The NuGet _package ID_ is `Microsoft.Azure.Workflows.WebJobs.Sdk`, but the _DLL_ inside the package is named `Microsoft.Azure.Functions.Extensions.Workflows.Sdk.dll`, and the _namespace_ for the `WorkflowActionTrigger` attribute is `Microsoft.Azure.Functions.Extensions.Workflows`. Three different naming conventions for the same thing. ### ⚠️ THE #2 MISTAKE: Wrong Namespace in Using Statements | Using statement | Compiles? | Correct? | | ------------------------------------------------------- | ---------- | -------- | | `using Microsoft.Azure.Workflows.WebJobs.Sdk;` | **NO** ❌ | ❌ | | `using Microsoft.Azure.Functions.Extensions.Workflows;` | **YES** ✅ | ✅ | **Both approaches use the same `[WorkflowActionTrigger]` attribute from the same namespace**. The difference is the function declaration attribute and its associated packages. ### Package Verification Command ```bash dotnet package search "Microsoft.Azure.Workflows" --take 5 # Expected result: Microsoft.Azure.Workflows.WebJobs.Sdk ``` --- ## 4. Approach A — .NET 8 (RECOMMENDED) ### 4.1 Project File (`Functions/Functions.csproj`) ```xml <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <IsPackable>false</IsPackable> <TargetFramework>net8</TargetFramework> <AzureFunctionsVersion>v4</AzureFunctionsVersion> <OutputType>Library</OutputType> <PlatformTarget>AnyCPU</PlatformTarget> <LogicAppFolderToPublish>$(MSBuildProjectDirectory)\..\my-logicapp</LogicAppFolderToPublish> <CopyToOutputDirectory>Always</CopyToOutputDirectory> <SelfContained>false</SelfContained> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Abstractions" Version="1.3.0" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.15.1" /> <PackageReference Include="Microsoft.Azure.Workflows.Webjobs.Sdk" Version="1.2.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" /> </ItemGroup> <Target Name="TriggerPublishOnBuild" AfterTargets="Build"> <CallTarget Targets="Publish" /> </Target> </Project> ``` ### 4.2 Critical csproj Details — .NET 8 | Property/Element | Value | Why It Matters | | ------------------------------ | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `<TargetFramework>` | `net8` | Must be `net8` — NOT `net8.0` (Logic Apps convention) | | `<AzureFunctionsVersion>` | `v4` | Required for Azure Functions v4 runtime | | `<OutputType>` | `Library` | Functions are libraries, not executables | | `<PlatformTarget>` | `AnyCPU` | Standard target for .NET 8 | | `<LogicAppFolderToPublish>` | `$(MSBuildProjectDirectory)\..\my-logicapp` | **Absolute path** to the sibling Logic App folder — the Publish target uses this to know where to deploy outputs. Replace `my-logicapp` with your Logic App folder name. | | `<SelfContained>` | `false` | Must NOT be self-contained — Logic Apps runtime provides the host | | `TriggerPublishOnBuild` target | Calls `Publish` AfterTargets `Build` | **This is the auto-deploy mechanism** — on every build, the Publish target automatically copies DLLs to `lib/custom/net8/` and function.json to `lib/custom/<FunctionName>/` inside the Logic App folder | > **IMPORTANT**: The .NET 8 approach uses a simple `TriggerPublishOnBuild` target that calls `Publish`. The Publish target (from the Worker SDK) handles all file copying automatically. You do NOT need manual copy targets. ### 4.3 Required Packages — .NET 8 | Package | Version | Why It's Needed |
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub