Creación y ejecución de código de .NET Framework desde flujos de trabajo estándar en Azure Logic Apps

Se aplica a: Azure Logic Apps (estándar)

Para las soluciones de integración en las que tiene que crear y ejecutar código de .NET Framework desde el flujo de trabajo de una aplicación lógica estándar, puede usar Visual Studio Code con la extensión de Azure Logic Apps (estándar). Esta extensión proporciona las siguientes funcionalidades y ventajas:

  • Escriba su propio código mediante la creación de funciones que tengan la flexibilidad y el control para resolver los problemas de integración más difíciles.
  • Depure código localmente en Visual Studio Code. Recorra el código y los flujos de trabajo en la misma sesión de depuración.
  • Implemente código junto con los flujos de trabajo. No es necesario ningún otro plan de servicio.
  • Admita escenarios de migración de BizTalk Server para que pueda migrar mediante lift-and-shift inversiones personalizadas de .NET Framework desde el entorno local a la nube.

Con la capacidad de escribir su propio código, puede lograr escenarios como los siguientes:

  • Implementación automática de lógica de negocios
  • Análisis personalizado para extraer información de un mensaje entrante
  • Validación de datos y transformaciones sencillas
  • Modelado de mensajes para mensajes salientes a otro sistema, como una API
  • Cálculos

Esta funcionalidad no es adecuada para escenarios como los siguientes:

  • Procesos que tardan más de 10 minutos en ejecutarse
  • Transformaciones de datos y mensajes grandes
  • Escenarios complejos de procesamiento por lotes y desagrupación
  • Los componentes de canalización de BizTalk Server que implementan streaming

Para obtener más información sobre las limitaciones de Azure Logic Apps, consulte Límites y configuración: Azure Logic Apps.

Prerrequisitos

Limitaciones

La creación de funciones personalizadas actualmente no está disponible en Azure Portal. Sin embargo, después de implementar las funciones desde Visual Studio Code en Azure, siga los pasos descritos en Llamada al código desde un flujo de trabajo para Azure Portal. Puede usar la acción integrada denominada Llamada a una función local en esta aplicación lógica para seleccionar entre las funciones personalizadas implementadas y ejecutar el código. Las acciones posteriores del flujo de trabajo pueden hacer referencia a las salidas de estas funciones, como en cualquier otro flujo de trabajo. Puede ver el historial de ejecución, las entradas y las salidas de la acción integrada.

Creación de un proyecto de código

La extensión más reciente de Azure Logic Apps (estándar) para Visual Studio Code incluye una plantilla de proyecto de código que proporciona una experiencia simplificada para escribir, depurar e implementar su propio código con los flujos de trabajo. Esta plantilla de proyecto crea un archivo de área de trabajo y dos proyectos de ejemplo: un proyecto para escribir el código, el otro proyecto para crear los flujos de trabajo.

Nota:

No puede usar la misma carpeta de proyecto para el código y los flujos de trabajo.

  1. Abra Visual Studio Code. En la barra de actividades, seleccione el icono de Azure. (Teclado: Mayús + Alt + A)

  2. En la ventana de Azure que se abre, en la barra de herramientas de la sección Área de trabajo, en el menú Azure Logic Apps, seleccione Crear una nueva área de trabajo de la aplicación lógica.

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

  3. En el cuadro Seleccionar carpeta, vaya a la carpeta local que creó para el proyecto y selecciónela.

  4. Cuando aparezca el cuadro Creación de un área de trabajo de aplicación lógica, proporcione un nombre para el área de trabajo:

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

    Este ejemplo continúa con MyLogicAppWorkspace.

  5. Cuando aparezca el cuadro Selección de una plantilla de proyecto para el área de trabajo de la aplicación lógica, seleccione Aplicación lógica con proyecto de código personalizado.

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

  6. Siga las solicitudes posteriores para proporcionar los siguientes valores de ejemplo:

    Elemento Valor de ejemplo
    Nombre de función para el proyecto de funciones WeatherForecast
    Nombre del espacio de nombres para el proyecto de funciones Contoso.Enterprise
    Plantilla de flujo de trabajo:
    - Flujo de trabajo con estado
    - Flujo de trabajo sin estado
    Flujo de trabajo con estado
    Nombre del flujo de trabajo MyWorkflow
  7. Seleccione Abrir en la ventana actual.

    Después de finalizar este paso, Visual Studio Code crea el área de trabajo, que incluye un proyecto de funciones y un proyecto de aplicación lógica, de manera predeterminada, por ejemplo:

    Screenshot shows Visual Studio Code with created workspace.

    Nodo Descripción
    <workspace-name> Contiene el proyecto de función y el proyecto de flujo de trabajo de la aplicación lógica.
    Funciones Contiene los artefactos del proyecto de función. Por ejemplo, el archivo <function-name>.cs es el archivo de código donde puede crear el código.
    LogicApp Contiene los artefactos del proyecto de aplicación lógica, incluido un flujo de trabajo en blanco.

Escritura del código

  1. En el área de trabajo, expanda el nodo Funciones, si aún no está expandido.

  2. Abra el archivo <function-name>.cs, que en este ejemplo se llama WeatherForecast.cs.

    De manera predeterminada, este archivo contiene código de ejemplo que tiene los siguientes elementos de código junto con los valores de ejemplo proporcionados anteriormente cuando corresponda:

    • Nombre del espacio de nombres
    • Nombre de la clase
    • Nombre de función
    • Parámetros de función
    • Tipo de valor devuelto
    • Tipo complejo

    A continuación se muestra un ejemplo de código de ejemplo completo:

    //------------------------------------------------------------
    // 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; }
            }
        }
    }
    

    La definición de función incluye un método predeterminado Run que puede usar para empezar. Este método Run de ejemplo muestra algunas de las funcionalidades disponibles con la característica de funciones personalizadas, como pasar diferentes entradas y salidas, incluidos los tipos complejos de .NET.

    El archivo <function-name>.cs también incluye la interfaz ILogger, que proporciona compatibilidad con el registro de eventos en un recurso de Application Insights. Puede enviar información de seguimiento a Application Insights y almacenar esa información junto con la información de seguimiento de los flujos de trabajo, por ejemplo:

    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. Reemplace el código de función de ejemplo por el suyo propio y edite el método Run predeterminado para sus propios escenarios. O bien, puede copiar la función, incluida la declaración [FunctionName("<*function-name*>")] y, a continuación, cambiar el nombre de la función por un nombre único. Puede editar la función que se volvió a nombrar para satisfacer sus necesidades.

Este ejemplo continúa con el código de ejemplo sin cambios.

Compilar y generar el código

Después de terminar de escribir el código, compile para asegurarse de que no existen errores de compilación. El proyecto de función incluye automáticamente tareas de compilación, que compilan y, después, agregan el código a la carpeta lib\custom del proyecto de aplicación lógica donde los flujos de trabajo buscan funciones personalizadas para ejecutar. Estas tareas colocan los ensamblados en la carpeta lib\custom\net472.

  1. En Visual Studio Code, desde el menú Terminal, seleccione Nuevo terminal.

  2. En la lista de directorios de trabajo que aparece, seleccione Funciones como directorio de trabajo actual para el nuevo terminal.

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

    Visual Studio Code abre una ventana de terminal con un símbolo del sistema.

  3. En la ventana Terminal, en el símbolo del sistema, escriba dotnet restore.

    Visual Studio Code analiza los proyectos y determina si están actualizados.

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

  4. Una vez que vuelva a aparecer el símbolo del sistema, escriba dotnet build. O bien, en el menú Terminal, seleccione Ejecutar tarea. En la lista de tareas, seleccione crear (Funciones).

    Si la compilación se realiza correctamente, la ventana Terminal informa que La compilación se realizó correctamente.

  5. Confirme que existen los siguientes elementos en el proyecto de aplicación lógica:

    • En el área de trabajo, expanda las carpetas siguientes: LogicApp>lib\custom>net472. Confirme que la subcarpeta denominada net472 contiene los archivos de varios ensamblados (DLL) necesarios para ejecutar el código, incluido un archivo denominado <nombre-de-la-función>.dll.

    • En el área de trabajo, expanda las carpetas siguientes: LogicApp>lib\custom><function-name>. Confirme que la subcarpeta denominada <nombre-de-la-función> contiene un archivo función.json, que incluye los metadatos sobre el código de función que escribió. El diseñador de flujo de trabajo usa este archivo para determinar las entradas y salidas necesarias al llamar al código.

    En el ejemplo siguiente se muestran ensamblados generados de ejemplo y otros archivos en el proyecto de aplicación lógica:

    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.

Llamar al código desde el flujo de trabajo

Después de confirmar que el código se compila y que el proyecto de aplicación lógica contiene los archivos necesarios para que se ejecute el código, abra el flujo de trabajo predeterminado incluido en el proyecto de aplicación lógica.

  1. En el área de trabajo, en LogicApp, expanda el nodo <workflow-name>, abra el menú contextual de workflow.json y seleccione Abrir Diseñador.

    En el diseñador de flujo de trabajo que se abre, el flujo de trabajo predeterminado, incluido con el proyecto de aplicación lógica, aparece con el siguiente desencadenador y acciones:

  2. Seleccione la acción llamada Llamar a una función local en esta aplicación lógica.

    El panel de información de la acción se abre a la derecha.

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

  3. Revise y confirme que el valor del parámetro Function Name está establecido en la función que desea ejecutar. Revise o cambie cualquier otro valor de parámetro que use la función.

Depuración del código y el flujo de trabajo

  1. Repita los pasos siguientes para iniciar el emulador de almacenamiento de Azurite tres veces: una vez cada uno para los siguientes servicios de Azure Storage:

    • Servicio Blob de Azure
    • Azure Queue Service
    • Servicio Tabla de Azure
    1. Desde el menú Vista de Visual Studio Code, seleccione Paleta de comandos.

    2. En el símbolo del sistema que aparece, busque y seleccione Azurite: Iniciar Blob Service.

    3. En la lista de directorios de trabajo que aparece, seleccione LogicApp.

    4. Repita estos pasos para Azurite: Iniciar Queue Service y Azurite: Iniciar Table Service.

    La operación es correcta si la barra de tareas de Visual Studio Code de la parte inferior de la pantalla muestra los tres servicios de almacenamiento en ejecución, por ejemplo:

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

  2. En la barra de actividad de Visual Studio Code, seleccione Ejecutar y depurar. (Teclado: Ctrl + Mayús + D)

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

  3. En la lista Ejecutar y depurar, seleccione Asociar a la aplicación lógica (LogicApp) si aún no está seleccionada y, a continuación, seleccione Reproducir (flecha verde).

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

    Se abre la ventana Terminal y se muestra el proceso de depuración iniciado. A continuación, aparece la ventana Consola de depuración y muestra los estados de depuración. En la parte inferior de Visual Studio Code, la barra de tareas se vuelve naranja, lo que indica que el depurador de .NET está cargado.

  4. En la lista Ejecutar y depurar, seleccione Asociar a funciones de .NET (Funciones) y, a continuación, seleccione Reproducir (flecha verde).

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

  5. Para establecer los puntos de interrupción, en la definición de la función (<function-name>.cs) o la definición del flujo de trabajo (workflow.json), busque el número de línea donde desee establecer el punto de interrupción y seleccione la columna a la izquierda, por ejemplo:

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

  6. Para ejecutar manualmente el desencadenador Solicitud en el flujo de trabajo, abra la página Información general del flujo de trabajo.

    1. En el proyecto de aplicación lógica, abra el menú contextual del archivo workflow.json y seleccione Información general.

      En la página Información general del flujo de trabajo, el botón Ejecutar desencadenador está disponible para cuando desee iniciar manualmente el flujo de trabajo. En Propiedades del flujo de trabajo, el valor de Dirección URL de devolución de llamada es la dirección URL de un punto de conexión al que se puede llamar creado por el desencadenador Solicitud en el flujo de trabajo. Puede enviar solicitudes a esta dirección URL para desencadenar el flujo de trabajo desde otras aplicaciones, incluidos otros flujos de trabajo de aplicaciones lógicas.

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

  7. En la barra de herramientas de la página Información general, seleccione Ejecutar desencadenador.

    Una vez que el flujo de trabajo comienza a ejecutarse, el depurador activa el primer punto de interrupción.

  8. En el menú Ejecutar o en la barra de herramientas del depurador, seleccione una acción de depuración.

    Una vez completada la ejecución del flujo de trabajo, la página Información general muestra la ejecución finalizada y los detalles básicos sobre esa ejecución.

  9. Para revisar más información sobre la ejecución del flujo de trabajo, seleccione la ejecución finalizada. O bien, en la lista situada junto a la columna Duración, seleccione Mostrar ejecución.

    Screenshot shows Visual Studio Code and finished workflow run.

Implementación del código

Puede implementar las funciones personalizadas de la misma manera que implementa el proyecto de aplicación lógica. Tanto si implementa desde Visual Studio Code como si usa un proceso de CI/CD de DevOps, asegúrese de compilar el código y de que todos los ensamblados dependientes existen en la carpeta lib/custom/net472 del proyecto de aplicación lógica antes de implementar. Para obtener más información, consulte Implementación de flujos de trabajo estándar de Visual Studio Code en Azure.

Solucionar problemas

Error del panel de información de acción

En el diseñador de flujos de trabajo, al seleccionar la acción integrada denominada Llamar a una función local en esta aplicación lógica, el panel de información de la acción muestra el mensaje siguiente:

Failed to retrieve dynamic inputs. Error details:

En este escenario, examine el proyecto de aplicación lógica para comprobar si la carpeta LogicApp\lib\custom está vacía. Si está vacía, en el menú Terminal, seleccione Ejecutar tarea>Compilar funciones.

Actualmente no se está ejecutando ningún proceso con el nombre especificado.

Si recibe este mensaje de error al ejecutar el flujo de trabajo, es probable que tenga el proceso del depurador asociado a funciones de .NET, en lugar de a la aplicación lógica.

Para solucionar este problema, en la lista Ejecutar y depurar, seleccione Asociar a la aplicación lógica (LogicApp) y, a continuación, seleccione Reproducir (flecha verde).

Paquete no importado correctamente

Si la ventana Salida muestra un error similar al siguiente mensaje, asegúrese de que tiene instalado .NET 6.0. Si tiene instalada esta versión, intente desinstalarla y volver a instalarla.

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]

Errores de compilación

Si la función no incluye variables y usted compila el código, la ventana Salida podría mostrar los siguientes mensajes de error:

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)

Para solucionar este problema, en el método Run del código, anexe el parámetro siguiente:

string parameter1 = null

En el ejemplo siguiente se muestra cómo aparece la firma del método Run:

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

Pasos siguientes

Creación de flujos de trabajo estándar con Visual Studio Code