Добавление и запуск скриптов C# с помощью стандартных рабочих процессов в Azure Logic Apps

Область применения: Azure Logic Apps (стандартная версия)

Чтобы выполнять пользовательские задачи интеграции в рамках рабочего процесса уровня "Стандартный" в Azure Logic Apps, вы можете напрямую добавлять и запускать скрипты C# из рабочего процесса. Для этой задачи используйте действие Встроенный код с названием Execute CSharp Script Code. Это действие возвращает результаты из скрипта, чтобы вы могли использовать эти выходные данные в последующих действиях рабочего процесса.

Эта возможность обеспечивает следующие преимущества:

  • Создайте собственные скрипты в конструкторе рабочих процессов, чтобы решить более сложные проблемы интеграции без необходимости использовать Функции Azure. Другие планы обслуживания не нужны.

    Это преимущество упрощает разработку рабочих процессов, а также снижает сложность и затраты с помощью управления дополнительными службами.

  • Создайте выделенный файл кода, который предоставляет персонализированное пространство сценариев в рабочем процессе.

  • Разверните скрипты вместе с рабочими процессами.

В этом руководстве показано, как добавить действие в рабочий процесс и добавить код скрипта C#, который требуется запустить.

Предварительные требования

  • Учетная запись и подписка Azure. Получите бесплатную учетную запись Azure.

  • Рабочий процесс стандартного приложения логики, в который вы хотите добавить скрипт C#. Рабочий процесс уже должен начинаться с триггера. Дополнительные сведения см. в разделе "Создание примеров стандартных рабочих процессов приложения логики".

    Для сценария можно использовать любой триггер, но в качестве примера в этом руководстве используется триггер запроса с именем "При получении HTTP-запроса ", а также действие "Ответ ". Рабочий процесс запускается, когда другое приложение или рабочий процесс отправляет запрос на URL-адрес конечной точки триггера. Пример скрипта возвращает результаты выполнения кода в виде выходных данных, которые можно использовать в последующих действиях.

Пример сценариев

В следующем списке описаны некоторые примеры сценариев, в которых можно использовать скрипт для выполнения определенных задач интеграции:

  • Анализировать полезную нагрузку и выполнять её преобразование или обработку сверх возможностей встроенных выражений и операций с данными. Например, можно использовать скрипт для возврата измененной схемы для последующей обработки.

  • Управляйте ресурсами Azure, такими как виртуальные машины, и запускайте или останавливайте их в соответствии с определённой бизнес-логикой.

  • Запустите хранимую процедуру на СЕРВЕРе SQL Server, который должен выполняться по расписанию и хранить результаты в SharePoint.

  • Регистрируйте ошибки рабочего процесса с подробной информацией, сохраняя их в служба хранилища Azure, отправляя по электронной почте или уведомляя свою команду.

  • Шифрование и расшифровка данных в соответствии со стандартами безопасности API.

  • Передайте файл в скрипт, чтобы заархивировать или распаковать его для HTTP-запроса.

  • Собирайте данные из различных API и файлов для создания ежедневных отчетов

Рекомендации

  • Портал Azure сохраняет ваш скрипт как файл сценария C# (.csx) в той же папке, что и файл workflow.json, в котором хранится определение вашего рабочего процесса в формате JSON, и развертывает этот файл в ресурсе вашего приложения логики вместе с определением рабочего процесса. Azure Logic Apps компилирует этот файл, чтобы скрипт был готов к выполнению.

    Формат файла .csx позволяет писать меньше шаблонного кода и сосредоточиться только на написании функции C#. Вы можете переименовать CSX-файл для упрощения управления во время развертывания. Однако при каждом переименовании скрипта новая версия перезаписывает предыдущую версию.

  • Сценарий является локальным для рабочего процесса. Чтобы использовать тот же сценарий в других рабочих процессах, просмотрите файл скрипта в консоли KuduPlus, а затем скопируйте скрипт для повторного использования в других рабочих процессах.

Ограничения

Имя Лимит Примечания.
Длительность выполнения скрипта 10 минут Если у вас есть сценарии, требующие более длительного времени, используйте функцию отправки отзывов о продукте, чтобы предоставить более подробную информацию о ваших потребностях.
Размер выходных данных 100 МБ Размер выходных данных зависит от предельного размера выходных данных для действий, что обычно составляет 100 МБ.

Добавление действия "Выполнение кода скрипта CSharp"

  1. На портале Azure откройте ресурс и рабочий процесс приложения логики уровня Standard в конструкторе.

  2. В конструкторе выполните следующие общие действия, чтобы добавить действие "Встроенные операции кода" с именем Execute CSharp Script Code в рабочий процесс.

  3. После открытия области сведений о действии на вкладке "Параметры " в поле "Файл кода" обновите предварительно заполненный пример кода с собственным кодом скрипта.

    В следующем примере показана вкладка "Параметры действия" с примером кода скрипта:

    Снимок экрана: портал Azure, конструктор стандартных рабочих процессов, триггер запроса, действие

    В следующем примере показан пример кода скрипта:

    /// Add the required libraries.
    #r "Newtonsoft.Json"
    #r "Microsoft.Azure.Workflows.Scripting"
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Primitives;
    using Microsoft.Extensions.Logging;
    using Microsoft.Azure.Workflows.Scripting;
    using Newtonsoft.Json.Linq;
    
    /// <summary>
    /// Executes the inline C# code.
    /// </summary>
    /// <param name="context">The workflow context.</param>
    /// <remarks> The entry-point to your code. The function signature should remain unchanged.</remarks>
    public static async Task<Results> Run(WorkflowContext context, ILogger log)
    {
        var triggerOutputs = (await context.GetTriggerResults().ConfigureAwait(false)).Outputs;
    
        /// Dereferences the 'name' property from the trigger payload.
        var name = triggerOutputs?["body"]?["name"]?.ToString();
    
        /// To get the outputs from a preceding action, you can uncomment and repurpose the following code.
        // var actionOutputs = (await context.GetActionResults("<action-name>").ConfigureAwait(false)).Outputs;
    
        /// The following logs appear in the Application Insights traces table.
        // log.LogInformation("Outputting results.");
        // var name = null;
    
        return new Results
        {
            Message = !string.IsNullOrEmpty(name) ? $"Hello {name} from CSharp action" : "Hello from CSharp action."
        };
    }
    
    public class Results
    {
        public string Message {get; set;}
    }
    

    Дополнительные сведения см. в разделе "#r" — ссылка на внешние сборки.

  4. По завершении сохраните рабочий процесс.

После запуска рабочего процесса можно просмотреть выходные данные рабочего процесса в Application Insights, если это включено. Дополнительные сведения см. в разделе "Просмотр журналов" в Application Insights.

Импорт пространств имен

Чтобы импортировать пространства имён, как обычно используйте конструкцию using. Следующий список включает автоматически импортированные пространства имен, поэтому они являются необязательными для включения в скрипт:

System
System.Collections.Generic
System.IO
System.Linq
System.Net.Http
System.Threading.Tasks
Microsoft.Azure.WebJobs
Microsoft.Azure.WebJobs.Host

Добавьте ссылки на внешние сборки

Чтобы ссылаться на сборки платформа .NET Framework, используйте директиву#r "<assembly-name>, например:

/// Add the required libraries.
#r "Newtonsoft.Json"
#r "Microsoft.Azure.Workflows.Scripting"
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Workflows.Scripting;
using Newtonsoft.Json.Linq;

public static async Task<Results> Run(WorkflowContext context)
{
    <...>
}

public class Results
{
    <...>
}

Следующий список включает сборки, автоматически добавленные средой размещения Функции Azure:

mscorlib
System
System.Core
System.Xml
System.Net.Http
Microsoft.Azure.WebJobs
Microsoft.Azure.WebJobs.Host
Microsoft.Azure.WebJobs.Extensions
System.Web.Http
System.Net.Http.Formatting
Newtonsoft.Json

Включение других файлов .csx

Если у вас есть CSX-файлы, можно использовать классы и методы из этих файлов в действии Execute CSharp Script Code . Для этой задачи можно использовать директиву #load в файле execute_csharp_code.csx . Эта директива работает только с CSX-файлами, а не с файлами .cs. Вам доступны следующие варианты:

  • Загрузите .csx-файл непосредственно в ваше действие.

    CSX-файл должен существовать в той же папке, что и рабочий процесс, содержащий действие Execute CSharp Script Code . См. статью Load .csx напрямую.

  • Ссылка на CSX-файл, который существует в общей папке для приложения логики.

    Общая папка должна существовать в пути к папке site/wwwroot/ для логического приложения. См. ссылку на csx-файл в общей папке.

Загрузка CSX-файла напрямую

В следующем примере файла execute_csharp_code.csx показано, как загрузить файл скрипта loadscript.csx в действие Execute CSharp Script Code с помощью директивы #load :

// Add the required libraries
#r "Newtonsoft.Json"
#r "Microsoft.Azure.Workflows.Scripting"
#load "loadscript.csx"
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Workflows.Scripting;
using Newtonsoft.Json.Linq;

/// <summary>
/// Execute the inline C# code.
/// </summary>
/// <param name="context">The workflow context.</param>
/// <remarks> This is the entry-point to your code. The function signature should remain unchanged.</remarks>
public static async Task<Results> Run(WorkflowContext context, ILogger log)
{
    var name = RunScript().ToString();
    return new Results
    {
        Message = !string.IsNullOrEmpty(name) ? $"Hello {name} from CSharp action" : "Hello from CSharp action."
    };
}

Ссылка на CSX-файл в общей папке

Директива #load позволяет ссылаться на CSX-файл, который существует в общей папке для ресурса приложения логики. Эта shared папка должна существовать в пути к папке site/wwwroot/ для ресурса приложения логики.

Чтобы добавить файл скрипта в папку shared , выполните следующие действия.

  1. На портале Azure откройте ресурс стандартного логического приложения.

  2. На боковой панели приложения логики в разделе "Средства разработки" выберите "Дополнительные инструменты".

  3. На странице "Дополнительные средства" выберите "Перейти", в котором откроется консоль Kudu+ .

  4. Откройте меню консоли отладки и выберите CMD.

  5. Перейдите в корневое расположение приложения логики: сайт/wwwroot

  6. Перейдите в общую папку. Если эта папка не существует, создайте папку.

    1. На панели инструментов рядом с именем папки выберите знак плюса (+), а затем выберите новую папку.

    2. Введите shared имя папки.

    3. Откройте новую shared папку.

  7. Перетащите файл скрипта для импорта в папку shared .

В следующем примере execute_csharp_code.csx-файл показано, как ссылаться на отправленный файл скрипта с именем importcript.csx в действие Execute CSharp Script Code с помощью директивы #load :

// Add the required libraries
#r "Newtonsoft.Json"
#r "Microsoft.Azure.Workflows.Scripting"
#load "..\shared\importscript.csx"
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Workflows.Scripting;
using Newtonsoft.Json.Linq;

/// <summary>
/// Execute the inline C# code.
/// </summary>
/// <param name="context">The workflow context.</param>
/// <remarks> This is the entry-point to your code. The function signature should remain unchanged.</remarks>
public static async Task<Results> Run(WorkflowContext context, ILogger log)
{
    var name = RunScript().ToString();
    return new Results
    {
        Message = !string.IsNullOrEmpty(name) ? $"Hello {name} from CSharp action" : "Hello from CSharp action." 
    }; 
} 

Импорт пакетов NuGet

NuGet — это поддерживаемый корпорацией Майкрософт способ создания, публикации, размещения, обнаружения, использования и совместного использования библиотек кода .NET, называемых пакетами. Действие Execute CSharp Script Code поддерживает возможность импорта пакетов NuGet с помощью файла functions.proj , расположенного в корне папки рабочего процесса, например:

site/wwwroot/<workflow-name>/workflow.json
site/wwwroot/<workflow-name>/functions.proj

Например, можно использовать следующий файл functions.proj для импорта пакетов NuGet в действие Execute CSharp Script Code :

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
       <TargetFramework>netstandard2.0</TargetFramework>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Serilog" Version="4.3.0" />
        <PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
        <PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
     </ItemGroup>
</Project>
  • Для файла скрипта C# (CSX) необходимо задать значение TargetFrameworknetstandard2.0.

    Это требование не означает, что версии пакетов ограничены netstandard2.0. Вы по-прежнему можете ссылаться на пакеты для net6.0 и более поздних версий.

  • При инициализации файла functions.proj необходимо перезапустить приложение логики, чтобы среда выполнения Azure Logic Apps может распознавать и использовать файл.

После завершения перезапуска среда выполнения автоматически получает необходимые сборки из NuGet.org и помещает сборку в соответствующую папку для использования скрипта. Хотя вам не нужно вручную загружать эти сборки, не забудьте напрямую ссылаться на пакеты в коде с помощью стандартных using инструкций, например:

using System.Net;
using Newtonsoft.Json;
using Serilog;

public static async Task<Output> Run(WorkflowContext context)
{
    Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Console()
    .CreateLogger();

    // Write log messages
    Log.Information("Hello, Serilog with Console sink!");
    Log.Warning("This is a warning message.");

    var outputReturn = new Output()
    { 
        Message = "Utilizing my serilog logger."
    }; 

    return outputReturn;
} 

public class Output
{ 
    public string Message { get; set; }
} 

Вывод журнала в поток

Run В методе добавьте параметр с ILogger типом и log именем, например:

public static void Run(WorkflowContext context, ILogger log)
{
    log.LogInformation($"C# script successfully executed.");
}

Вывод журналов в Application Insights

Чтобы создать пользовательские метрики в Application Insights, используйте метод расширения LogMetric для ILogger.

В следующем примере показан пример вызова метода:

logger.LogMetric("TestMetric", 1234);

Получите доступ к выходным данным триггера и действия рабочего процесса в скрипте

Чтобы получить доступ к данным из рабочего процесса, используйте следующие методы, доступные для объекта контекста WorkflowContext :

  • GetTriggerResultsМетод

    Чтобы получить доступ к выходным данным триггера, используйте этот метод для возврата объекта, представляющего триггер и его выходные данные, доступные через Outputs свойство. Этот объект имеет тип JObject , и вы можете использовать квадратные скобки ([]) в качестве индексатора для доступа к различным свойствам в выходных данных триггера.

    Следующий пример получает данные из свойства body в выходных данных триггера:

    public static async Task<Results> Run(WorkflowContext context, ILogger log)
    {
    
        var triggerOutputs = (await context.GetTriggerResults().ConfigureAwait(false)).Outputs;
        var body = triggerOutputs["body"];
    
        return new Results;
    
    }
    
    public class Results
    {
        <...>
    }
    
  • GetActionResultsМетод

    Чтобы получить доступ к выходным данным действия, используйте этот метод для возврата объекта, представляющего действие и его выходные данные, доступные через Outputs свойство. Этот метод принимает имя действия в качестве параметра. Следующий пример получает данные из свойства body в выходных данных действия с именем action-name:

    public static async Task<Results> Run(WorkflowContext context, ILogger log)
    {
    
        var actionOutputs = (await context.GetActionResults("action-name").ConfigureAwait(false)).Outputs;
        var body = actionOutputs["body"];
    
        return new Results;
    
    }
    
    public class Results
    {
        <...>
    }
    

Доступ к переменным среды или значению параметра приложения

Чтобы получить переменную среды или значение параметра приложения, используйте System.Environment.GetEnvironmentVariable этот метод, например:

public static void Run(WorkflowContext context, ILogger log)
{
    log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
    log.LogInformation(GetEnvironmentVariable("AzureWebJobsStorage"));
    log.LogInformation(GetEnvironmentVariable("WEBSITE_SITE_NAME"));
}

public static string GetEnvironmentVariable(string name)
{
    return name + ": " +
    System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process);
}

Возврат данных в рабочий процесс

Для этой задачи реализуйте свой метод Run с типом возвращаемого значения и инструкцией return. Если требуется асинхронная версия, реализуйте Run метод с атрибутом Task<return-type> и ключевым словом async . Возвращаемое значение присваивается свойству выходных body данных действия скрипта, на которое затем могут ссылаться любые последующие действия рабочего процесса.

В следующем примере показаны Run метод с атрибутом Task<Results>, ключевое слово async и инструкция return:

public static async Task<Results> Run(WorkflowContext context, ILogger log)
{
    return new Results
    {
        Message = !string.IsNullOrEmpty(name) ? $"Returning results with status message."
    };
}

public class Results
{
    public string Message {get; set;}
}

Просмотр файла скрипта

  1. На портале Azure откройте ресурс стандартного приложения логики с нужным рабочим процессом.

  2. На боковой панели приложения логики в разделе "Средства разработки" выберите "Дополнительные инструменты".

  3. На странице "Дополнительные средства" выберите "Перейти", который открывает консоль KuduPlus.

  4. Откройте меню консоли отладки и выберите CMD.

  5. Перейдите в корневое расположение приложения логики: сайт/wwwroot

  6. Перейдите в папку рабочего процесса, содержащую CSX-файл, по этому пути: site/wwwroot/{workflow-name}

  7. Рядом с именем файла нажмите кнопку "Изменить ", чтобы открыть файл и просмотреть его.

Просмотреть журналы в Application Insights

  1. На портале Azure на боковой панели приложения логики в разделе "Параметры" выберите Application Insights. Выберите приложение логики.

  2. На боковой панели Application Insights в разделе "Мониторинг" выберите "Журналы".

  3. Создайте запрос для поиска трассировок или ошибок из выполнения рабочего процесса, например:

    union traces, errors
    | project TIMESTAMP, message
    

Ошибки компиляции

В этом выпуске веб-редактор включает ограниченную поддержку IntelliSense, которая по-прежнему находится под улучшением. Все ошибки компиляции обнаруживаются при сохранении рабочего процесса, а среда выполнения Azure Logic Apps компилирует скрипт. Эти ошибки отображаются в журналах ошибок приложения логики.

Ошибки среды выполнения

Если при выполнении скрипта возникает ошибка, Azure Logic Apps выполняет следующие действия:

  • Передает ошибку обратно в рабочий процесс.
  • Помечает действие скрипта как сбой.
  • Предоставляет объект ошибки, представляющий исключение, вызванное скриптом.

В следующем примере показана пример ошибки:

Функция "CSharp_MyLogicApp-InvalidAction_execute_csharp_script_code.csx" завершилась ошибкой "Несуществующее действие не существует в рабочем процессе". при выполнении. Убедитесь, что код функции действителен.

Примеры скриптов

Следующие примеры скриптов выполняют различные задачи, которые вы можете

Распакуйте ZIP-файл с текстовыми файлами из HTTP-действия в массив строк

// Add the required libraries.
#r "Newtonsoft.Json"
#r "Microsoft.Azure.Workflows.Scripting"
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Microsoft.Azure.Workflows.Scripting;
using System;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Collections.Generic;

/// <summary>
/// Executes the inline C# code.
/// </summary>
/// <param name="context">The workflow context.</param>
public static async Task<List<string>> Run(WorkflowContext context)
{

    var outputs = (await context.GetActionResults("HTTP_1").ConfigureAwait(false)).Outputs;
    var base64zipFileContent = outputs["body"]["$content"].ToString();

    // Decode base64 to bytes.
    byte[] zipBytes = Convert.FromBase64String(base64zipFileContent);

    List<string> fileContents = new List<string>();

    // Creates an in-memory stream from the zip bytes.
    using (MemoryStream zipStream = new MemoryStream(zipBytes))
    {

        // Extracts files from the zip archive.
        using (ZipArchive zipArchive = new ZipArchive(zipStream))
        {

            foreach (ZipArchiveEntry entry in zipArchive.Entries)
            {

                // Read each file's content.
                using (StreamReader reader = new StreamReader(entry.Open()))
                {
                    string fileContent = reader.ReadToEnd();
                    fileContents.Add(fileContent);
                }
            }
        }
    }

    return fileContents;
}

Шифрование данных с помощью ключа из параметров приложения

// Add the required libraries.
#r "Newtonsoft.Json"
#r "Microsoft.Azure.Workflows.Scripting"
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Microsoft.Azure.Workflows.Scripting;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

/// <summary>
/// Executes the inline csharp code.
/// </summary>
/// <param name="context">The workflow context.</param>
public static async Task<string> Run(WorkflowContext context)
{

    var compose = (await context.GetActionResults("compose").ConfigureAwait(false)).Outputs;
    var text = compose["sampleData"].ToString();

    return EncryptString(text);

}

public static string EncryptString(string plainText)
{

    var key = Environment.GetEnvironmentVariable("app-setting-key");
    var iv = Environment.GetEnvironmentVariable("app-setting-iv");

    using (Aes aesAlg = Aes.Create())
    {

        aesAlg.Key = Encoding.UTF8.GetBytes(key);
        aesAlg.IV = Encoding.UTF8.GetBytes(iv);
        ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

        using (MemoryStream msEncrypt = new MemoryStream())
        {

            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            {

                using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                {
                    swEncrypt.Write(plainText);
                }

            }

             return Convert.ToBase64String(msEncrypt.ToArray());

        }
    }
}

Класс WorkflowContext

Представляет контекст рабочего процесса.

Методы

GetActionResult(string actionName)

Возвращает результат конкретного действия в рабочем процессе.

Асинхронная версия использует task<> в качестве возвращаемого типа, например:

Task<WorkflowOperationResult> GetActionResult(string actionName)

Параметры

actionName: имя действия.

Возвраты

Асинхронная версия возвращает Task объект, представляющий асинхронную операцию. Результат задачи содержит WorkflowOperationResult объект. Сведения о свойствах объекта WorkflowOperationResult см. в классе WorkflowOperationResult.

RunTriggerResult()

Получает результат из триггера в рабочем процессе.

Асинхронная версия использует task<> в качестве возвращаемого типа, например:

Task<WorkflowOperationResult> RunTriggerResult()

Параметры

Нет.

Возвраты

Асинхронная версия возвращает Task объект, представляющий асинхронную операцию. Результат задачи содержит WorkflowOperationResult объект. Сведения о свойствах объекта WorkflowOperationResult см. в классе WorkflowOperationResult.

Класс WorkflowOperationResult

Представляет собой результат операции рабочего процесса.

Свойства

Имя Тип Описание
Имя Строка Возвращает или задает имя операции.
Входные данные JToken Возвращает или задает входные данные выполнения операции.
Выходные данные JToken Возвращает или задает выходные данные выполнения операции.
StartTime DateTime? Возвращает или задает время начала операции.
EndTime DateTime? Возвращает или задает время окончания операции.
OperationTrackingId Строка Возвращает или задает идентификатор отслеживания операций.
Код Строка Возвращает или задает код состояния для данного действия.
Состояние Строка Возвращает или задает статус действия.
Ошибка JToken Возвращает или задает ошибку для действия.
TrackedProperties JToken Возвращает или задает отслеживаемые свойства для действия.

Добавление и запуск фрагментов кода JavaScript