Guía para ejecutar C# Azure Functions en un proceso de trabajo aislado

Este artículo es una introducción al trabajo con el proceso de trabajo aislado de .NET Functions, que ejecuta las funciones en un proceso de trabajo aislado en Azure. Esto le permite ejecutar las funciones de la biblioteca de clases de .NET en una versión de .NET diferente de la versión usada por el proceso de host de Functions. Para obtener información sobre las versiones específicas de .NET admitidas, consulte versión compatible.

Use los vínculos siguientes para empezar a compilar de inmediato funciones de proceso de trabajo aislado de .NET.

Introducción Conceptos Ejemplos

Si todavía necesita ejecutar las funciones en el mismo proceso que el host, consulte Funciones de biblioteca de clases de C# en proceso.

Para obtener una comparación completa entre las funciones de .NET en proceso y de proceso de trabajo aislado, consulte Diferencias entre Azure Functions con .NET en proceso y de proceso de trabajo aislado.

¿Por qué el proceso de trabajo aislado de .NET Functions?

Cuando se introdujo, Azure Functions solo admitía un modo estrechamente integrado para las funciones de .NET. En este modo en proceso, las funciones de la biblioteca de clases de .NET se ejecutan en el mismo proceso que el host. Este modo proporciona una integración profunda entre el proceso de host y las funciones. Por ejemplo, cuando se ejecutan en el mismo proceso, las funciones de biblioteca de clases de .NET pueden compartir tipos y API de enlace. Sin embargo, esta integración también requiere un acoplamiento más estrecho entre el proceso de host y la función de .NET. Por ejemplo, las funciones de .NET que se ejecutan en proceso deben ejecutarse en la misma versión de .NET que el entorno de ejecución de Functions. Esto significa que las funciones en proceso solo se pueden ejecutar en la versión de .NET con Soporte técnico a largo plazo (LTS). Para permitir que se ejecute en una versión que no sea LTS de .NET, puede optar por realizar la ejecución en un proceso de trabajo aislado. Este aislamiento de procesos permite desarrollar funciones que usan versiones actuales de .NET no admitidas de forma nativa por el runtime de Functions, incluyendo .NET Framework. Tanto las funciones de biblioteca de clases C# en proceso como las de proceso de trabajo aislado se ejecutan en versiones LTS. Para obtener más información, consulte Versiones compatibles.

Dado que estas funciones se ejecutan en un proceso independiente, existen algunas diferencias entre las características y las funciones de las aplicaciones de funciones aisladas de .NET y las de la biblioteca de clases .NET.

Ventajas del proceso de trabajo aislado

Cuando las funciones de .NET se ejecutan en un proceso de trabajo aislado, puede aprovechar las ventajas siguientes:

  • Menos conflictos: dado que las funciones se ejecutan en un proceso independiente, los ensamblados usados en la aplicación no entrarán en conflicto con la versión diferente de los mismos ensamblados que usa el proceso de host.
  • Control total del proceso: el usuario controla el inicio de la aplicación y puede controlar las configuraciones usadas y el middleware iniciado.
  • Inserción de dependencias: dado que tiene control total del proceso, puede usar los comportamientos actuales de .NET para la inserción de dependencias e incorporar middleware a la aplicación de funciones.

Versiones compatibles

Las versiones del entorno en tiempo de ejecución de Functions funcionan con versiones específicas de .NET. Para obtener más información sobre las versiones de Functions, consulte Introducción a las versiones de tiempo de ejecución de Azure Functions. La compatibilidad con versiones depende de si las funciones se ejecutan en proceso o como proceso de trabajo aislado.

Nota

Para aprender a cambiar la versión del runtime de Functions que usa la aplicación de funciones, consulte la sesión Visualización y actualización de la versión actual del entorno de ejecución.

En la tabla siguiente se muestra el nivel más alto de .NET Core o .NET Framework que se puede usar con una versión específica de Functions.

Versiones del entorno en tiempo de ejecución de Functions En proceso
(Biblioteca de clases .NET)
Proceso de trabajo aislado
(.NET aislado)
Functions 4.x .NET 6.0 .NET 6.0
.NET 7.0 (GA)1
.NET Framework 4.8 (GA)1
Functions 1.x .NET Framework 4.8 N/D

1 El proceso de compilación también requiere el SDK de .NET 6.

Para obtener las últimas noticias sobre las versiones de Azure Functions, incluida la eliminación de versiones secundarias específicas anteriores, revise los anuncios de Azure App Service.

Proyecto de proceso de trabajo aislado de .NET

Un proyecto de función aislada de .NET es básicamente un proyecto de aplicación de consola de .NET que tiene como destino un runtime .NET compatible. A continuación, se muestran los archivos básicos necesarios en cualquier proyecto aislado de .NET:

Para ejemplos completos, consulte el proyecto de ejemplo aislado de .NET 6 y el proyecto de ejemplo aislado de .NET Framework 4.8.

Nota

Para poder publicar el proyecto de función aislado en una aplicación de funciones de Windows o Linux en Azure, debe establecer un valor de dotnet-isolated en la configuración de la aplicación remota dotnet-isolated. Para admitir la implementación de ZIP y la ejecución desde el paquete de implementación en Linux, también debe actualizar la configuración del sitio a . Para más información, vea Actualizaciones manuales de versiones en Linux.

Referencias de paquete

Un proyecto de proceso de trabajo aislado de .NET Functions usa un conjunto único de paquetes, tanto para la funcionalidad principal como para las extensiones de enlace.

Paquetes base

Los siguientes paquetes son necesarios para ejecutar las funciones de .NET en un proceso de trabajo aislado:

Paquetes de extensión

Dado que las funciones de proceso de trabajo aislado de .NET usan tipos de enlace diferentes, requieren un conjunto único de paquetes de extensión de enlace.

Encontrará estos paquetes de extensión en Microsoft.Azure.Functions.Worker.Extensions.

Inicio y configuración

Cuando se usan funciones aisladas de .NET, se tiene acceso al inicio de la aplicación de funciones, que normalmente se encuentra en Program.cs. El usuario es responsable de crear e iniciar su propia instancia de host. Como tal, también tiene acceso directo a la canalización de configuración de la aplicación. Con el proceso de trabajo aislado de .NET Functions, puede agregar configuraciones mucho más fácilmente, insertar dependencias y ejecutar su propio middleware.

El código siguiente muestra un ejemplo de una canalización de HostBuilder:

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(builder =>
    {
        builder
            .AddApplicationInsights()
            .AddApplicationInsightsLogger();
    })
    .ConfigureServices(s =>
    {
        s.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
    })
    .Build();

Este código requiere using Microsoft.Extensions.DependencyInjection;.

Un HostBuilder se utiliza para compilar y devolver una instancia de IHost completamente inicializada, que se ejecuta de forma asincrónica para iniciar la aplicación de funciones.

await host.RunAsync();

Importante

Si el proyecto tiene como destino .NET Framework 4.8, también debe agregar FunctionsDebugger.Enable(); antes de crear HostBuilder. Debe ser la primera línea del método Main(). Consulte Depuración al utilizar .NET Framework como destino para más información.

Configuración

El método ConfigureFunctionsWorkerDefaults se usa para agregar la configuración necesaria para que la aplicación de funciones se ejecute en un proceso de trabajo aislado, lo que incluye la siguiente funcionalidad:

  • Conjunto predeterminado de convertidores.
  • Establezca el valor predeterminado de JsonSerializerOptions para omitir mayúsculas y minúsculas en los nombres de propiedad.
  • Integre con el registro de Azure Functions.
  • Middleware y características de enlace de salida.
  • Middleware de ejecución de función.
  • Soporte de gRPC predeterminado.
.ConfigureFunctionsWorkerDefaults(builder =>
{
    builder
        .AddApplicationInsights()
        .AddApplicationInsightsLogger();
})

El acceso a la canalización del generador de host significa que también puede establecer cualquier configuración específica de la aplicación durante la inicialización. Puede llamar al método ConfigureAppConfiguration en HostBuilder una o varias veces para agregar las configuraciones requeridas por la aplicación de funciones. Para más información sobre la configuración de la aplicación, consulte Configuración en ASP.NET Core.

Estas configuraciones se aplican a la aplicación de funciones que se ejecuta en un proceso independiente. Para realizar cambios en el host de funciones o en la configuración del enlace y el desencadenador, todavía necesitará usar el archivo host.json.

Inserción de dependencias

La inserción de dependencias se simplifica, en comparación con las bibliotecas de clases .NET. En lugar de tener que crear una clase de inicio para registrar los servicios, solo tiene que llamar a ConfigureServices en el generador de host y usar los métodos de extensión en IServiceCollection para insertar servicios específicos.

En el ejemplo siguiente se inserta una dependencia del servicio singleton:

.ConfigureServices(s =>
{
    s.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
})

Este código requiere using Microsoft.Extensions.DependencyInjection;. Para obtener más información, consulte Inserción de dependencias en ASP.NET Core.

Software intermedio

.NET aislado también admite el registro de middleware, de nuevo mediante un modelo similar a lo que existe en ASP.NET. Este modelo proporciona la capacidad de insertar lógica en la canalización de invocación, y antes y después de que se ejecuten las funciones.

El método de extensión ConfigureFunctionsWorkerDefaults tiene una sobrecarga que le permite registrar su propio middleware, como puede ver en el ejemplo siguiente.

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(workerApplication =>
    {
        // Register our custom middlewares with the worker

        workerApplication.UseMiddleware<ExceptionHandlingMiddleware>();

        workerApplication.UseMiddleware<MyCustomMiddleware>();

        workerApplication.UseWhen<StampHttpHeaderMiddleware>((context) =>
        {
            // We want to use this middleware only for http trigger invocations.
            return context.FunctionDefinition.InputBindings.Values
                          .First(a => a.Type.EndsWith("Trigger")).Type == "httpTrigger";
        });
    })
    .Build();

El método de extensión UseWhen se puede usar para registrar un middleware que se ejecuta condicionalmente. Debe pasar a este método un predicado que devuelve un valor booleano y el middleware participa en la canalización de procesamiento de invocación cuando el valor devuelto del predicado es true.

Los métodos de extensión siguientes en FunctionContext facilitan el trabajo con el middleware en el modelo aislado.

Método Descripción
GetHttpRequestDataAsync Obtiene la instancia HttpRequestData cuando la llamada la realiza un desencadenador HTTP. Este método devuelve una instancia de ValueTask<HttpRequestData?>, que es útil cuando desea leer datos de mensajes, como encabezados de solicitud y cookies.
GetHttpResponseData Obtiene la instancia HttpResponseData cuando la llamada la realiza un desencadenador HTTP.
GetInvocationResult Obtiene una instancia de InvocationResult, que representa el resultado de la ejecución de la función actual. Utilice la propiedad Value para obtener o establecer el valor según sea necesario.
GetOutputBindings Obtiene las entradas de enlace de salida para la ejecución de la función actual. Cada entrada del resultado de este método es de tipo OutputBindingData. Puede utilizar la propiedad Value para obtener o establecer el valor según sea necesario.
BindInputAsync Enlaza un elemento de enlace de entrada para la instancia BindingMetadata solicitada. Por ejemplo, puede usar este método cuando tenga una función con un enlace de entrada BlobInput al que el middleware necesita tener acceso o actualizar.

A continuación se muestra un ejemplo de una implementación de middleware que lee la instancia HttpRequestData y actualiza la instancia HttpResponseData durante la ejecución de la función. Este middleware comprueba la presencia de un encabezado de solicitud específico (x-correlationId) y, cuando está presente, usa el valor de encabezado para poner un sello en un encabezado de respuesta. De lo contrario, genera un nuevo valor GUID y lo usa para poner un sello en el encabezado de respuesta.

internal sealed class StampHttpHeaderMiddleware : IFunctionsWorkerMiddleware
{
    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        var requestData = await context.GetHttpRequestDataAsync();

        string correlationId;
        if (requestData!.Headers.TryGetValues("x-correlationId", out var values))
        {
            correlationId = values.First();
        }
        else
        {
            correlationId = Guid.NewGuid().ToString();
        }

        await next(context);

        context.GetHttpResponseData()?.Headers.Add("x-correlationId", correlationId);
    }
}

Para obtener un ejemplo más completo del uso de middleware personalizado en la aplicación de funciones, consulte el ejemplo de referencia de middleware personalizado.

Tokens de cancelación

Una función puede aceptar un parámetro CancellationToken que permite que el sistema operativo notifique al código cuando la función esté a punto de finalizar. Puede utilizar esta notificación para asegurarse de que la función no se termina inesperadamente en una forma que deje los datos en un estado incoherente.

Los tokens de cancelación se admiten en funciones de .NET cuando se ejecutan en un proceso de trabajo aislado. En el ejemplo siguiente se genera una excepción cuando se ha recibido una solicitud de cancelación:

[Function(nameof(ThrowOnCancellation))]
public async Task ThrowOnCancellation(
    [EventHubTrigger("sample-workitem-1", Connection = "EventHubConnection")] string[] messages,
    FunctionContext context,
    CancellationToken cancellationToken)
{
    _logger.LogInformation("C# EventHub {functionName} trigger function processing a request.", nameof(ThrowOnCancellation));

    foreach (var message in messages)
    {
        cancellationToken.ThrowIfCancellationRequested();
        await Task.Delay(6000); // task delay to simulate message processing
        _logger.LogInformation("Message '{msg}' was processed.", message);
    }
}

En el ejemplo siguiente se realizan acciones de limpieza si se ha recibido una solicitud de cancelación:

[Function(nameof(HandleCancellationCleanup))]
public async Task HandleCancellationCleanup(
    [EventHubTrigger("sample-workitem-2", Connection = "EventHubConnection")] string[] messages,
    FunctionContext context,
    CancellationToken cancellationToken)
{
    _logger.LogInformation("C# EventHub {functionName} trigger function processing a request.", nameof(HandleCancellationCleanup));

    foreach (var message in messages)
    {
        if (cancellationToken.IsCancellationRequested)
        {
            _logger.LogInformation("A cancellation token was received, taking precautionary actions.");
            // Take precautions like noting how far along you are with processing the batch
            _logger.LogInformation("Precautionary activities complete.");
            break;
        }

        await Task.Delay(6000); // task delay to simulate message processing
        _logger.LogInformation("Message '{msg}' was processed.", message);
    }
}

ReadyToRun

La aplicación de funciones se puede compilar como archivos binarios de ReadyToRun. ReadyToRun es una forma de compilación Ahead Of Time que puede mejorar el rendimiento de inicio para ayudar a reducir el impacto del inicio en frío cuando se ejecuta en un plan de consumo.

ReadyToRun está disponible en .NET 6 (y versiones posteriores) y requiere la versión 4.0 o posterior del runtime de Azure Functions.

Para compilar un proyecto como ReadyToRun, actualice el archivo del proyecto agregando los elementos <PublishReadyToRun> y <RuntimeIdentifier>. A continuación se encuentra la configuración para publicar en una aplicación de funciones de Windows de 32 bits.

<PropertyGroup>
  <TargetFramework>net6.0</TargetFramework>
  <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  <RuntimeIdentifier>win-x86</RuntimeIdentifier>
  <PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>

Contexto de ejecución

.NET aislado pasa un objeto FunctionContext en los métodos de función. Este objeto permite obtener una instancia de ILogger para escribir en los registros llamando al método GetLogger y proporcionando una cadena . Para más información, consulte Registro.

Enlaces

Los enlaces se definen mediante atributos en métodos, parámetros y tipos de valor devuelto. Un método de función es un método con un atributo Function y un atributo de desencadenador aplicados a un parámetro de entrada, tal como se muestra en el ejemplo siguiente:

[Function("QueueFunction")]
[QueueOutput("output-queue")]
public static string[] Run([QueueTrigger("input-queue")] Book myQueueItem, FunctionContext context)

El atributo desencadenador especifica el tipo de desencadenador y enlaza los datos de entrada a un parámetro del método. La función de ejemplo anterior se desencadena mediante un mensaje de cola, y este último se pasa al método en el parámetro myQueueItem.

El atributo Function marca el método como punto de entrada de una función. El nombre debe ser único dentro de un proyecto, debe empezar por una letra y solo puede incluir letras, números, _ y -, y hasta 127 caracteres. Las plantillas de proyecto suelen crear un método denominado Run, pero el nombre de método puede ser cualquier nombre de método de C# válido.

En su lugar, los enlaces se basan en cadenas, matrices y tipos serializables, como los objetos de clase anterior sin formato (POCO). También puede enlazar a tipos de algunos SDK de servicio.

En el caso de los desencadenadores HTTP, debe usar HttpRequestData y HttpResponseData para tener acceso a los datos de solicitud y respuesta. Esto se debe a que no tiene acceso a los objetos de solicitud y respuesta HTTP originales cuando se usa el proceso de trabajo aislado de .NET Functions.

Para obtener un conjunto completo de ejemplos de referencia para usar desencadenadores y enlaces con funciones de proceso de trabajo aislado, consulte el ejemplo de referencia de extensiones de enlace.

Enlaces de entrada

Una función puede tener cero o más enlaces de entrada que pueden pasar datos a una función. Al igual que los desencadenadores, los enlaces de entrada se definen mediante la aplicación de un atributo de enlace a un parámetro de entrada. Cuando se ejecuta la función, el entorno de ejecución intenta obtener los datos especificados en el enlace. Los datos que se solicitan suelen depender de la información proporcionada por el desencadenador mediante parámetros de enlace.

Enlaces de salida

Para escribir en un enlace de salida, debe aplicar un atributo de enlace de salida al método de función, que define cómo escribir en el servicio enlazado. El valor devuelto por el método se escribe en el enlace de salida. Por ejemplo, en el ejemplo siguiente se escribe un valor de cadena en una cola de mensajes denominada output-queue mediante un enlace de salida:

[Function("QueueFunction")]
[QueueOutput("output-queue")]
public static string[] Run([QueueTrigger("input-queue")] Book myQueueItem, FunctionContext context)
{
    // Use a string array to return more than one message.
    string[] messages = {
        $"Book name = {myQueueItem.Name}",
        $"Book ID = {myQueueItem.Id}"};
    var logger = context.GetLogger("QueueFunction");
    logger.LogInformation($"{messages[0]},{messages[1]}");

    // Queue Output messages
    return messages;
}

Varios enlaces de salida

Los datos que se escriben en un enlace de salida siempre son el valor devuelto de la función. Si tiene que escribir en más de un enlace de salida, debe crear un tipo de valor devuelto personalizado. Este tipo de valor devuelto debe tener el atributo de enlace de salida aplicado a una o más propiedades de la clase. El ejemplo siguiente de un desencadenador HTTP escribe en una respuesta HTTP y en un enlace de salida de cola:

public static class MultiOutput
{
    [Function("MultiOutput")]
    public static MyOutputType Run([HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestData req,
        FunctionContext context)
    {
        var response = req.CreateResponse(HttpStatusCode.OK);
        response.WriteString("Success!");

        string myQueueOutput = "some output";

        return new MyOutputType()
        {
            Name = myQueueOutput,
            HttpResponse = response
        };
    }
}

public class MyOutputType
{
    [QueueOutput("myQueue")]
    public string Name { get; set; }

    public HttpResponseData HttpResponse { get; set; }
}

La respuesta de un desencadenador HTTP siempre se considera una salida, por lo que no se requiere un atributo de valor devuelto.

Tipos de SDK (versión preliminar)

Para algunos tipos de enlace específicos del servicio, se pueden proporcionar datos de enlace mediante tipos de SDK de servicio y marcos de trabajo. Estas proporcionan funcionalidad adicional más allá de lo que puede ofrecer una cadena serializada o un objeto CLR sin formato (POCO). La compatibilidad con los tipos de SDK se encuentra actualmente en versión preliminar con cobertura de escenario limitada.

Para usar enlaces de tipo de SDK, el proyecto debe hacer referencia a Microsoft.Azure.Functions.Worker 1.12.1-preview1 o posterior y Microsoft.Azure.Functions.Worker.Sdk 1.9.0-preview1 o posterior. También se necesitarán versiones de paquete específicas para cada una de las extensiones de servicio. Al probar los tipos de SDK localmente en la máquina, también deberá usar Azure Functions Core Tools versión 4.0.5000 o posterior. Puede comprobar la versión actual mediante el comando func version.

Los siguientes enlaces específicos del servicio se incluyen actualmente en la versión preliminar:

Servicio Desencadenador Enlace de entrada Enlace de salida
Azure Blobs Compatibilidad con la versión preliminar Compatibilidad con la versión preliminar Sin compatibilidad aún1
Azure Cosmos DB Tipos de SDK no usados2 Compatibilidad con la versión preliminar Sin compatibilidad aún1

1 La compatibilidad con los enlaces de tipo SDK no se extiende actualmente a los enlaces de salida.

2 El desencadenador de Cosmos DB usa la fuente de cambios de Azure Cosmos DB y expone elementos de fuente de cambios como tipos serializables JSON. La ausencia de tipos de SDK es por diseño para este escenario.

Los ejemplos de enlace de tipos del SDK muestran ejemplos de trabajo con los distintos tipos admitidos.

Nota

Al usar expresiones de enlace que se basan en datos de desencadenador, no se admiten los tipos de SDK para el propio desencadenador.

Desencadenador HTTP

Los desencadenadores HTTP permiten invocar una función mediante una solicitud HTTP. Hay dos enfoques diferentes que se pueden usar:

Modelos HTTP integrados

En el modelo integrado, el sistema traduce el mensaje de solicitud HTTP entrante en un objeto HttpRequestData que se pasa a la función. Este objeto proporciona datos de la solicitud, incluidos Headers, Cookies, Identities, URL y un mensaje opcional Body. Este objeto es una representación de la solicitud HTTP, pero no está conectado directamente al agente de escucha HTTP subyacente o al mensaje recibido.

Del mismo modo, la función devuelve un objeto HttpReponseData, que proporciona los datos usados para crear la respuesta HTTP, incluido el del mensaje, Headers y, opcionalmente, un Body de mensaje.

El siguiente ejemplo muestra el uso de HttpRequestData y HttpResponseData:

[Function("HttpFunction")]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequestData req,
    FunctionContext executionContext)
{
    var logger = executionContext.GetLogger("HttpFunction");
    logger.LogInformation("message logged");

    var response = req.CreateResponse(HttpStatusCode.OK);
   
    response.Headers.Add("Content-Type", "text/plain; charset=utf-8");

    response.WriteString("Welcome to .NET isolated worker !!");

    return response;
}

integración de ASP.NET Core (versión preliminar)

En esta sección se muestra cómo trabajar con los objetos de solicitud y respuesta HTTP subyacentes mediante tipos de ASP.NET Core incluidos HttpRequest, HttpResponse e IActionResult. El uso de esta característica para las pruebas locales requiere Core Tools versión 4.0.5198 o posterior. Este modelo no está disponible para las aplicaciones destinadas a .NET Framework, que en su lugar deben aprovechar el modelo integrado.

Nota

Este modelo no expone todas las características de ASP.NET Core. En concreto, la ASP.NET Core canalización de middleware y las funcionalidades de enrutamiento no están disponibles. En las versiones preliminares iniciales del paquete de integración, falta información de ruta de los objetos HttpRequest y HttpContext y se debe realizar el acceso a los parámetros de ruta a través del objeto FunctionContext o a través de la inserción de parámetros.

  1. Agregue una referencia al paquete NuGet Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore al proyecto.

También debe actualizar el proyecto para que use la versión 1.10.0 o posterior de Microsoft.Azure.Functions.Worker.Sdk y la versión 1.14.1 o posterior de Microsoft.Azure.Functions.Worker.

  1. En el archivo Program.cs, actualice la configuración del generador de hosts para incluir los métodos UseAspNetCoreIntegration() y ConfigureAspNetCoreIntegration(). En el ejemplo siguiente se muestra una configuración mínima sin otras personalizaciones:

    using Microsoft.Extensions.Hosting;
    using Microsoft.Azure.Functions.Worker;
    
    var host = new HostBuilder()
        .ConfigureFunctionsWorkerDefaults(workerApplication =>
        {
            workerApplication.UseAspNetCoreIntegration();
        })
        .ConfigureAspNetCoreIntegration()
        .Build();
    
    host.Run();
    

    Nota

    Las versiones preliminares iniciales del paquete de integración requieren que se llamen a UseAspNetCoreIntegration() y ConfigureAspNetCoreIntegration(), pero estos pasos de instalación aún no se han finalizado.

  2. A continuación, puede actualizar las funciones desencadenadas por HTTP para usar los tipos de ASP.NET Core. En el ejemplo siguiente se muestra que se usa HttpRequest y un IActionResult para una función simple «hello, world»:

    [Function("HttpFunction")]
    public IActionResult Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req)
    {
        return new OkObjectResult($"Welcome to Azure Functions, {req.Query["name"]}!");
    }
    
  3. Habilite la característica estableciendo AzureWebJobsFeatureFlags para incluir "EnableHttpProxying". Cuando se hospeda en una aplicación de funciones, configúrelo como una configuración de aplicación. Cuando se ejecuta localmente, establezca este valor en local.settings.json.

Registro

En .NET aislado, puede escribir en los registros mediante una instancia de ILogger obtenida de un objeto FunctionContext pasado a la función. Llame al método GetLogger, pasando un valor de cadena que es el nombre de la categoría en la que se escriben los registros. La categoría suele ser el nombre de la función específica desde la que se escriben los registros. Para obtener más información sobre las categorías, consulte el artículo sobre supervisión.

En el ejemplo siguiente se muestra cómo obtener un ILogger y escribir registros dentro de una función:

var logger = executionContext.GetLogger("HttpFunction");
logger.LogInformation("message logged");

Use diferentes métodos de ILogger para escribir varios niveles de registro, como o LogError. Para obtener más información sobre los niveles de registro, consulte el artículo sobre supervisión.

También se proporciona un ILogger al usar la inserción de dependencias.

Depuración al utilizar .NET Framework como destino

Si el proyecto aislado tiene como destino .NET Framework 4.8, el ámbito de versión preliminar actual requiere pasos manuales para habilitar la depuración. Estos pasos no son necesarios si se usa otra plataforma de destino.

La aplicación debe empezar con una llamada a FunctionsDebugger.Enable(); como primera operación. Esto ocurre en el método Main() antes de inicializar un HostBuilder. El archivo Program.cs debe tener un aspecto similar al siguiente:

using System;
using System.Diagnostics;
using Microsoft.Extensions.Hosting;
using Microsoft.Azure.Functions.Worker;
using NetFxWorker;

namespace MyDotnetFrameworkProject
{
    internal class Program
    {
        static void Main(string[] args)
        {
            FunctionsDebugger.Enable();

            var host = new HostBuilder()
                .ConfigureFunctionsWorkerDefaults()
                .Build();

            host.Run();
        }
    }
}

A continuación, debe asociarse manualmente al proceso mediante un depurador de .NET Framework. Visual Studio no hace esto automáticamente para aplicaciones de .NET Framework de proceso de trabajo aislado y se debe evitar la operación "Iniciar depuración".

En el directorio del proyecto (o su directorio de salida de compilación), ejecute:

func host start --dotnet-isolated-debug

Esto iniciará el trabajo y el proceso se detendrá con el siguiente mensaje:

Azure Functions .NET Worker (PID: <process id>) initialized in debug mode. Waiting for debugger to attach...

Donde <process id> es el id. del proceso de trabajo. Ahora puede usar Visual Studio para asociarse manualmente al proceso. Para instrucciones sobre esta operación, consulte Asociación con un proceso en ejecución.

Una vez asociado el depurador, la ejecución del proceso se reanuda y podrá depurar.

Depuración remota con Visual Studio

Dado que la aplicación de proceso de trabajo aislado se ejecuta fuera del entorno de ejecución de Functions, debe asociar el depurador remoto a un proceso independiente. Para obtener más información sobre la depuración mediante Visual Studio, consulte Depuración remota.

Pasos siguientes