Guida per l'esecuzione di Funzioni di Azure C# nel modello di lavoro isolato

Questo articolo è un'introduzione all'uso di Funzioni di Azure in .NET, usando il modello di lavoro isolato. Questo modello consente al progetto di scegliere come destinazione le versioni di .NET indipendentemente da altri componenti di runtime. Per informazioni sulle versioni specifiche di .NET supportate, vedere la versione supportata.

Usare i collegamenti seguenti per iniziare subito a creare funzioni del modello di lavoro isolato .NET.

Introduzione Concetti Esempi

Per informazioni sulla distribuzione di un progetto di modello di lavoro isolato in Azure, vedere Distribuire in Funzioni di Azure.

Vantaggi del modello di lavoro isolato

Esistono due modalità in cui è possibile eseguire le funzioni della libreria di classi .NET: nello stesso processo del runtime dell'host di Funzioni (in-process) o in un processo di lavoro isolato. Quando le funzioni .NET vengono eseguite in un processo di lavoro isolato, è possibile sfruttare i vantaggi seguenti:

  • Meno conflitti: poiché le funzioni vengono eseguite in un processo separato, gli assembly usati nell'app non sono in conflitto con versioni diverse degli stessi assembly usati dal processo host.
  • Controllo completo del processo: si controlla l'avvio dell'app, il che significa che è possibile gestire le configurazioni usate e il middleware avviato.
  • Inserimento di dipendenze standard: poiché si ha il controllo completo del processo, è possibile usare i comportamenti .NET correnti per l'inserimento delle dipendenze e incorporare middleware nell'app per le funzioni.
  • Flessibilità della versione .NET: l'esecuzione all'esterno del processo host significa che le funzioni possono essere eseguite in versioni di .NET non supportate in modo nativo dal runtime di Funzioni, incluso .NET Framework.

Se si dispone di un'app per le funzioni C# esistente che viene eseguita in-process, è necessario eseguire la migrazione dell'app per sfruttare questi vantaggi. Per altre informazioni, vedere Eseguire la migrazione di app .NET dal modello in-process al modello di lavoro isolato.

Per un confronto completo tra le due modalità, vedere Differenze tra processi in-process e isolare i processi di lavoro Funzioni di Azure .NET.

Versioni supportate

Le versioni del runtime di Funzioni supportano versioni specifiche di .NET. Per altre informazioni sulle versioni di Funzioni, vedere Funzioni di Azure panoramica delle versioni di runtime. Il supporto della versione dipende anche dal fatto che le funzioni eseguano il processo di lavoro in-process o isolato.

Nota

Per informazioni su come modificare la versione del runtime di Funzioni usata dall'app per le funzioni, vedere Visualizzare e aggiornare la versione di runtime corrente.

La tabella seguente illustra il livello più elevato di .NET o .NET Framework che può essere usato con una versione specifica di Funzioni.

Versione del runtime di Funzioni Modello di lavoro isolato Modello in-process5
Funzioni 4.x .NET 8.0
.NET 7.01
.NET 6.02
.NET Framework 4.83
.NET 6.02
Funzioni 1.x4 n/d .NET Framework 4.8

1 .NET 7 raggiunge la fine del supporto ufficiale il 14 maggio 2024.
2 .NET 6 raggiunge la fine del supporto ufficiale il 12 novembre 2024.
3 Il processo di compilazione richiede anche .NET SDK. 4 Il supporto termina per la versione 1.x del runtime Funzioni di Azure il 14 settembre 2026. Per altre informazioni, vedere questo annuncio di supporto. Per il supporto completo continuo, è consigliabile eseguire la migrazione delle app alla versione 4.x.
5 Il supporto termina per il modello in-process il 10 novembre 2026. Per altre informazioni, vedere questo annuncio di supporto. Per un supporto completo continuo, è consigliabile eseguire la migrazione delle app al modello di lavoro isolato.

Per le ultime notizie sulle versioni Funzioni di Azure, inclusa la rimozione di versioni secondarie meno recenti specifiche, monitorare gli annunci del servizio app Azure.

Struttura progetto

Un progetto .NET per Funzioni di Azure che usa il modello di lavoro isolato è fondamentalmente un progetto di app console .NET destinato a un runtime .NET supportato. Di seguito sono riportati i file di base necessari in qualsiasi progetto isolato .NET:

  • File di progetto C# (con estensione csproj) che definisce il progetto e le dipendenze.
  • Program.cs file che rappresenta il punto di ingresso per l'app.
  • Tutti i file di codice che definiscono le funzioni.
  • host.json file che definisce la configurazione condivisa dalle funzioni nel progetto.
  • local.settings.json file che definisce le variabili di ambiente usate dal progetto quando vengono eseguite localmente nel computer.

Per esempi completi, vedere il progetto di esempio .NET 8 e il progetto di esempio .NET Framework 4.8.

Riferimenti ai pacchetti

Un progetto .NET per Funzioni di Azure che usa il modello di lavoro isolato usa un set univoco di pacchetti, sia per le funzionalità di base che per le estensioni di associazione.

Pacchetti core

Per eseguire le funzioni .NET in un processo di lavoro isolato sono necessari i pacchetti seguenti:

Pacchetti di estensione

Poiché le funzioni del processo di lavoro isolato .NET usano tipi di associazione diversi, richiedono un set univoco di pacchetti di estensioni di associazione.

Questi pacchetti di estensione sono disponibili in Microsoft.Azure.Functions.Worker.Extensions.

Avvio e configurazione

Quando si usano funzioni isolate .NET, è possibile accedere all'avvio dell'app per le funzioni, che in genere si trova in Program.cs. Si è responsabili della creazione e dell'avvio di un'istanza host personalizzata. Di conseguenza, si ha anche accesso diretto alla pipeline di configurazione per l'app. Con il processo di lavoro isolato di Funzioni .NET, è possibile aggiungere con maggiore facilità configurazioni, inserire dipendenze ed eseguire il proprio middleware.

Il codice seguente illustra un esempio di pipeline HostBuilder :

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(s =>
    {
        s.AddApplicationInsightsTelemetryWorkerService();
        s.ConfigureFunctionsApplicationInsights();
        s.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
        s.Configure<LoggerFilterOptions>(options =>
        {
            // The Application Insights SDK adds a default logging filter that instructs ILogger to capture only Warning and more severe logs. Application Insights requires an explicit override.
            // Log levels can also be configured using appsettings.json. For more information, see https://learn.microsoft.com/en-us/azure/azure-monitor/app/worker-service#ilogger-logs
            LoggerFilterRule toRemove = options.Rules.FirstOrDefault(rule => rule.ProviderName
                == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");

            if (toRemove is not null)
            {
                options.Rules.Remove(toRemove);
            }
        });
    })
    .Build();

Questo codice richiede using Microsoft.Extensions.DependencyInjection;.

Prima di chiamare Build() su HostBuilder, è necessario:

  • ConfigureFunctionsWebApplication() Chiamare se si usa l'integrazione di ASP.NET Core o ConfigureFunctionsWorkerDefaults() in caso contrario. Per informazioni dettagliate su queste opzioni, vedere Trigger HTTP.
    Se si scrive l'applicazione usando F#, alcune estensioni di trigger e binding richiedono una configurazione aggiuntiva. Vedere la documentazione di installazione per l'estensione BLOB, l'estensione Tabelle e l'estensione Cosmos DB quando si prevede di usare queste estensioni in un'app F#.
  • Configurare i servizi o la configurazione dell'app necessari per il progetto. Per informazioni dettagliate, vedere Configurazione .
    Se si prevede di usare Application Insights, è necessario chiamare AddApplicationInsightsTelemetryWorkerService() e ConfigureFunctionsApplicationInsights() nel ConfigureServices() delegato. Per informazioni dettagliate, vedere Application Insights .

Se il progetto è destinato a .NET Framework 4.8, è necessario aggiungere FunctionsDebugger.Enable(); anche prima di creare HostBuilder. Deve essere la prima riga del Main() metodo. Per altre informazioni, vedere Debug quando la destinazione è .NET Framework.

HostBuilder viene usato per compilare e restituire un'istanza completamente inizializzataIHost, eseguita in modo asincrono per avviare l'app per le funzioni.

await host.RunAsync();

Impostazione

Il metodo ConfigureFunctionsWorkerDefaults viene usato per aggiungere le impostazioni necessarie per l'esecuzione dell'app per le funzioni in un processo di lavoro isolato, che include le funzionalità seguenti:

  • Set predefinito di convertitori.
  • Impostare l'opzione JsonSerializerOptions predefinita per ignorare le maiuscole e minuscole nei nomi delle proprietà.
  • Eseguire l'integrazione con la registrazione di Funzioni di Azure.
  • Middleware e funzionalità di associazione di output.
  • Middleware di esecuzione della funzione.
  • Supporto gRPC predefinito.
.ConfigureFunctionsWorkerDefaults()

Avere accesso alla pipeline del generatore host significa che è anche possibile impostare qualsiasi configurazione specifica dell'app durante l'inizializzazione. È possibile chiamare il metodo ConfigureAppConfiguration in HostBuilder una o più volte per aggiungere le configurazioni richieste dall'app per le funzioni. Per altre informazioni sulla configurazione delle app, vedere Configurazione in ASP.NET Core.

Queste configurazioni si applicano all'app per le funzioni in esecuzione in un processo separato. Per apportare modifiche alla configurazione dell'host o del trigger e dell'associazione delle funzioni, è comunque necessario usare il file di host.json.

Nota

Non è possibile usare origini di configurazione personalizzate per la configurazione di trigger e associazioni. La configurazione del trigger e dell'associazione deve essere disponibile per la piattaforma funzioni e non solo per il codice dell'applicazione. È possibile fornire questa configurazione tramite le impostazioni dell'applicazione, i riferimenti a Key Vault o Configurazione app funzionalità di riferimento.

Inserimento delle dipendenze

L'inserimento delle dipendenze è semplificato rispetto alle funzioni in-process di .NET. È quindi necessario creare una classe di avvio per registrare i servizi.

Per un'app di processo isolato .NET, si usa il modo standard .NET di chiamare ConfigureServices nel generatore host e usare i metodi di estensione in IServiceCollection per inserire servizi specifici.

Nell'esempio seguente viene inserita una dipendenza del servizio singleton:

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

Questo codice richiede using Microsoft.Extensions.DependencyInjection;. Per altre informazioni, vedere Inserimento delle dipendenze in ASP.NET Core.

Registrare i client di Azure

L'inserimento delle dipendenze può essere usato per interagire con altri servizi di Azure. È possibile inserire i client da Azure SDK per .NET usando il pacchetto Microsoft.Extensions.Azure . Dopo aver installato il pacchetto, registrare i client chiamando AddAzureClients() nella raccolta di servizi in Program.cs. L'esempio seguente configura un client denominato per i BLOB di Azure:

using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices((hostContext, services) =>
    {
        services.AddAzureClients(clientBuilder =>
        {
            clientBuilder.AddBlobServiceClient(hostContext.Configuration.GetSection("MyStorageConnection"))
                .WithName("copierOutputBlob");
        });
    })
    .Build();

host.Run();

L'esempio seguente illustra come usare questo tipo di registrazione e SDK per copiare il contenuto del BLOB come flusso da un contenitore a un altro usando un client inserito:

using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Logging;

namespace MyFunctionApp
{
    public class BlobCopier
    {
        private readonly ILogger<BlobCopier> _logger;
        private readonly BlobContainerClient _copyContainerClient;

        public BlobCopier(ILogger<BlobCopier> logger, IAzureClientFactory<BlobServiceClient> blobClientFactory)
        {
            _logger = logger;
            _copyContainerClient = blobClientFactory.CreateClient("copierOutputBlob").GetBlobContainerClient("samples-workitems-copy");
            _copyContainerClient.CreateIfNotExists();
        }

        [Function("BlobCopier")]
        public async Task Run([BlobTrigger("samples-workitems/{name}", Connection = "MyStorageConnection")] Stream myBlob, string name)
        {
            await _copyContainerClient.UploadBlobAsync(name, myBlob);
            _logger.LogInformation($"Blob {name} copied!");
        }

    }
}

In ILogger<T> questo esempio è stato ottenuto anche tramite l'inserimento delle dipendenze, quindi viene registrato automaticamente. Per altre informazioni sulle opzioni di configurazione per la registrazione, vedere Registrazione.

Suggerimento

Nell'esempio è stata usata una stringa letterale per il nome del client sia in che nella Program.cs funzione . Considerare invece l'uso di una stringa costante condivisa definita nella classe della funzione. Ad esempio, è possibile aggiungere e quindi fare public const string CopyStorageClientName = nameof(_copyContainerClient); riferimento BlobCopier.CopyStorageClientName in entrambe le posizioni. È possibile definire in modo analogo il nome della sezione di configurazione con la funzione anziché in Program.cs.

Middleware

.NET isolato supporta anche la registrazione del middleware, anche se si usa un modello simile a quello presente in ASP.NET. Questo modello consente di inserire la logica nella pipeline di chiamata e prima e dopo l'esecuzione delle funzioni.

Il metodo di estensione ConfigureFunctionsWorkerDefaults include un overload che consente di registrare il proprio middleware, come illustrato nell'esempio seguente.

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();

Il UseWhen metodo di estensione può essere usato per registrare un middleware che viene eseguito in modo condizionale. È necessario passare a questo metodo un predicato che restituisce un valore booleano e il middleware partecipa alla pipeline di elaborazione delle chiamate quando il valore restituito del predicato è true.

I metodi di estensione seguenti in FunctionContext semplificano l'uso del middleware nel modello isolato.

metodo Descrizione
GetHttpRequestDataAsync Ottiene l'istanza HttpRequestData quando viene chiamata da un trigger HTTP. Questo metodo restituisce un'istanza di ValueTask<HttpRequestData?>, utile quando si desidera leggere i dati dei messaggi, ad esempio intestazioni di richiesta e cookie.
GetHttpResponseData Ottiene l'istanza HttpResponseData quando viene chiamata da un trigger HTTP.
GetInvocationResult Ottiene un'istanza di InvocationResult, che rappresenta il risultato dell'esecuzione della funzione corrente. Utilizzare la Value proprietà per ottenere o impostare il valore in base alle esigenze.
GetOutputBindings Ottiene le voci di associazione di output per l'esecuzione della funzione corrente. Ogni voce nel risultato di questo metodo è di tipo OutputBindingData. È possibile utilizzare la Value proprietà per ottenere o impostare il valore in base alle esigenze.
BindInputAsync Associa un elemento di associazione di input per l'istanza richiesta BindingMetadata . Ad esempio, è possibile usare questo metodo quando si dispone di una funzione con un'associazione BlobInput di input che deve essere usata dal middleware.

Questo è un esempio di implementazione del middleware che legge l'istanza e aggiorna l'istanza HttpRequestData durante l'esecuzione HttpResponseData della funzione:

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

Questo middleware verifica la presenza di un'intestazione di richiesta specifica (x-correlationId) e, quando presente, usa il valore dell'intestazione per contrassegnare un'intestazione di risposta. In caso contrario, genera un nuovo valore GUID e lo usa per contrassegnare l'intestazione della risposta. Per un esempio più completo dell'uso di middleware personalizzato nell'app per le funzioni, vedi l'esempio di riferimento del middleware personalizzato.

Personalizzazione della serializzazione JSON

Il modello di lavoro isolato usa per System.Text.Json impostazione predefinita. È possibile personalizzare il comportamento del serializzatore configurando i servizi come parte del Program.cs file. L'esempio seguente illustra l'uso di ConfigureFunctionsWebApplication, ma funziona anche per ConfigureFunctionsWorkerDefaults:

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication((IFunctionsWorkerApplicationBuilder builder) =>
    {
        builder.Services.Configure<JsonSerializerOptions>(jsonSerializerOptions =>
        {
            jsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
            jsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
            jsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;

            // override the default value
            jsonSerializerOptions.PropertyNameCaseInsensitive = false;
        });
    })
    .Build();

È possibile usare invece JSON.NET (Newtonsoft.Json) per la serializzazione. A tale scopo, installare il Microsoft.Azure.Core.NewtonsoftJson pacchetto. Quindi, nella registrazione del servizio, si riassegna la Serializer proprietà nella WorkerOptions configurazione. L'esempio seguente illustra l'uso di ConfigureFunctionsWebApplication, ma funziona anche per ConfigureFunctionsWorkerDefaults:

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication((IFunctionsWorkerApplicationBuilder builder) =>
    {
        builder.Services.Configure<WorkerOptions>(workerOptions =>
        {
            var settings = NewtonsoftJsonObjectSerializer.CreateJsonSerializerSettings();
            settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            settings.NullValueHandling = NullValueHandling.Ignore;

            workerOptions.Serializer = new NewtonsoftJsonObjectSerializer(settings);
        });
    })
    .Build();

Metodi riconosciuti come funzioni

Un metodo function è un metodo pubblico di una classe pubblica con un Function attributo applicato al metodo e un attributo trigger applicato a un parametro di input, come illustrato nell'esempio seguente:

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

L'attributo trigger specifica il tipo di trigger e associa i dati di input a un parametro del metodo. La funzione di esempio precedente viene attivata da un messaggio della coda e il messaggio della coda viene passato al metodo nel myQueueItem parametro .

L'attributo Function indica il metodo come punto di ingresso della funzione. Il nome deve essere univoco all'interno di un progetto, iniziare con una lettera e contenere solo lettere, numeri, _e -, fino a 127 caratteri di lunghezza. I modelli di progetto spesso creano un metodo denominato Run, ma il nome del metodo può essere qualsiasi nome di metodo c# valido. Il metodo deve essere un membro pubblico di una classe pubblica. In genere deve essere un metodo di istanza in modo che i servizi possano essere passati tramite inserimento delle dipendenze.

Parametri di funzione

Ecco alcuni dei parametri che è possibile includere come parte di una firma del metodo di funzione:

  • Binding, contrassegnati come tali mediante la decorazione dei parametri come attributi. La funzione deve contenere esattamente un parametro trigger.
  • Oggetto contesto di esecuzione, che fornisce informazioni sulla chiamata corrente.
  • Token di annullamento, usato per l'arresto normale.

Contesto di esecuzione

.NET isolato passa un oggetto FunctionContext ai metodi della funzione. Questo oggetto consente di ottenere un'istanza ILogger per scrivere nei log chiamando il metodo GetLogger e fornendo una categoryName stringa. È possibile usare questo contesto per ottenere un oggetto senza dover usare l'inserimento ILogger delle dipendenze. Per altre informazioni, vedere Registrazione.

Token di annullamento

Una funzione può accettare un parametro CancellationToken, che consente al sistema operativo di notificare il codice quando la funzione sta per essere terminata. È possibile usare questa notifica per assicurarsi che la funzione non termini in modo imprevisto lasciando i dati in uno stato incoerente.

I token di annullamento sono supportati nelle funzioni .NET quando vengono eseguiti in un processo di lavoro isolato. L'esempio seguente genera un'eccezione quando viene ricevuta una richiesta di annullamento:

[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);
    }
}

Nell'esempio seguente vengono eseguite azioni di pulizia quando viene ricevuta una richiesta di annullamento:

[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);
    }
}

Bindings

Le associazioni vengono definite usando attributi su metodi, parametri e tipi restituiti. Le associazioni possono fornire dati come stringhe, matrici e tipi serializzabili, ad esempio oggetti di classe precedenti (POCO). Per alcune estensioni di associazione, è anche possibile eseguire il binding a tipi specifici del servizio definiti negli SDK del servizio.

Per i trigger HTTP, vedere la sezione trigger HTTP.

Per un set completo di esempi di riferimento che usano trigger e associazioni con funzioni di processo di lavoro isolate, vedere l'esempio di riferimento delle estensioni di associazione.

Associazioni di input

Una funzione può avere zero o più associazioni di input che possono passare dati a una funzione. Come i trigger, le associazioni di input vengono definite applicando un attributo di associazione a un parametro di input. Quando la funzione viene eseguita, il runtime tenta di ottenere i dati specificati nell'associazione. I dati richiesti dipendono spesso dalle informazioni fornite dal trigger tramite parametri di associazione.

Associazioni di output

Per scrivere in un'associazione di output, è necessario applicare un attributo di associazione di output al metodo della funzione, che definisce come scrivere nel servizio associato. Il valore restituito dal metodo viene scritto nell'associazione di output. L'esempio seguente, ad esempio, scrive un valore stringa in una coda di messaggi denominata output-queue usando un'associazione di output:

[Function(nameof(QueueFunction))]
[QueueOutput("output-queue")]
public string[] Run([QueueTrigger("input-queue")] Album myQueueItem, FunctionContext context)
{
    // Use a string array to return more than one message.
    string[] messages = {
        $"Album name = {myQueueItem.Name}",
        $"Album songs = {myQueueItem.Songs.ToString()}"};

    _logger.LogInformation("{msg1},{msg2}", messages[0], messages[1]);

    // Queue Output messages
    return messages;
}

Più associazioni di output

I dati scritti in un'associazione di output sono sempre il valore restituito della funzione. Se è necessario scrivere in più associazioni di output, è necessario creare un tipo restituito personalizzato. Questo tipo restituito deve avere l'attributo di associazione di output applicato a una o più proprietà della classe . L'esempio seguente da un trigger HTTP scrive sia nella risposta HTTP che in un'associazione di output della coda:

public static class MultiOutput
{
    [Function(nameof(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 risposta da un trigger HTTP viene sempre considerata un output, quindi non è necessario un attributo del valore restituito.

Tipi di SDK

Per alcuni tipi di associazione specifici del servizio, è possibile fornire dati di associazione usando tipi di SDK e framework del servizio. Questi offrono più funzionalità oltre a quanto può offrire una stringa serializzata o un oggetto CLR normale (POCO). Per usare i tipi più recenti, il progetto deve essere aggiornato per usare le versioni più recenti delle dipendenze principali.

Dipendenza Requisito della versione
Microsoft.Azure.Functions.Worker 1.18.0 o versione successiva
Microsoft.Azure.Functions.Worker.Sdk 1.13.0 o versione successiva

Quando si testano i tipi di SDK in locale nel computer, è anche necessario usare Funzioni di Azure Core Tools, versione 4.0.5000 o successiva. È possibile controllare la versione corrente usando il func version comando .

Ogni estensione di trigger e binding ha anche un proprio requisito di versione minima, descritto negli articoli di riferimento sulle estensioni. Le associazioni specifiche del servizio seguenti forniscono tipi di SDK:

Servizio Trigger Associazione di input Associazione di output
BLOB di Azure Disponibile a livello generale Disponibile a livello generale Tipi SDK non consigliati.1
Code di Azure Disponibile a livello generale L'associazione di input non esiste Tipi SDK non consigliati.1
Bus di servizio di Azure Disponibile a livello generale L'associazione di input non esiste Tipi SDK non consigliati.1
Hub eventi di Azure Disponibile a livello generale L'associazione di input non esiste Tipi SDK non consigliati.1
Azure Cosmos DB Tipi SDK non usati2 Disponibile a livello generale Tipi SDK non consigliati.1
Tabelle di Azure Il trigger non esiste Disponibile a livello generale Tipi SDK non consigliati.1
Griglia di eventi di Azure Disponibile a livello generale L'associazione di input non esiste Tipi SDK non consigliati.1

1 Per gli scenari di output in cui si usa un tipo di SDK, è consigliabile creare e usare direttamente i client SDK anziché usare un'associazione di output. Vedere Registrare i client di Azure per un esempio di inserimento delle dipendenze.

2 Il trigger di Cosmos DB usa il feed di modifiche di Azure Cosmos DB ed espone gli elementi del feed di modifiche come tipi serializzabili JSON. L'assenza di tipi SDK è progettata per questo scenario.

Nota

Quando si usano espressioni di associazione che si basano sui dati del trigger, non è possibile usare i tipi SDK per il trigger stesso.

Trigger HTTP

I trigger HTTP consentono di richiamare una funzione da una richiesta HTTP. Esistono due approcci diversi che è possibile usare:

  • Modello di integrazione ASP.NET Core che usa i concetti noti agli sviluppatori di base ASP.NET
  • Modello predefinito, che non richiede dipendenze aggiuntive e usa tipi personalizzati per le richieste e le risposte HTTP. Questo approccio viene mantenuto per garantire la compatibilità con le versioni precedenti delle app di lavoro isolate .NET.

Integrazione di ASP.NET Core

Questa sezione illustra come usare gli oggetti richiesta e risposta HTTP sottostanti usando i tipi di ASP.NET Core, tra cui HttpRequest, HttpResponse e IActionResult. Questo modello non è disponibile per le app destinate a .NET Framework, che deve invece usare il modello predefinito.

Nota

Non tutte le funzionalità di ASP.NET Core sono esposte da questo modello. In particolare, le funzionalità di routing e pipeline middleware core ASP.NET non sono disponibili. ASP.NET'integrazione core richiede l'uso di pacchetti aggiornati.

Per abilitare l'integrazione di ASP.NET Core per HTTP:

  1. Aggiungere un riferimento nel progetto al pacchetto Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore , versione 1.0.0 o successiva.

  2. Aggiornare il progetto per usare queste versioni specifiche del pacchetto:

  3. Program.cs Nel file aggiornare la configurazione del generatore host in modo da usare ConfigureFunctionsWebApplication() invece di ConfigureFunctionsWorkerDefaults(). L'esempio seguente mostra una configurazione minima senza altre personalizzazioni:

    using Microsoft.Extensions.Hosting;
    using Microsoft.Azure.Functions.Worker;
    
    var host = new HostBuilder()
        .ConfigureFunctionsWebApplication()
        .Build();
    
    host.Run();
    
  4. Aggiornare tutte le funzioni attivate da HTTP esistenti per usare i tipi di base ASP.NET. Questo esempio mostra lo standard HttpRequest e un IActionResult oggetto usato per una semplice funzione "hello, world":

    [Function("HttpFunction")]
    public IActionResult Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req)
    {
        return new OkObjectResult($"Welcome to Azure Functions, {req.Query["name"]}!");
    }
    

Modello HTTP predefinito

Nel modello predefinito, il sistema converte il messaggio di richiesta HTTP in ingresso in un oggetto HttpRequestData passato alla funzione. Questo oggetto fornisce dati dalla richiesta, tra cui Headers, CookiesIdentities, URL, e facoltativamente un messaggio Body. Questo oggetto è una rappresentazione della richiesta HTTP, ma non è direttamente connesso al listener HTTP sottostante o al messaggio ricevuto.

Analogamente, la funzione restituisce un oggetto HttpResponseData , che fornisce i dati usati per creare la risposta HTTP, incluso il messaggio StatusCode, Headerse facoltativamente un messaggio Body.

Nell'esempio seguente viene illustrato l'uso di HttpRequestData e HttpResponseData:

[Function(nameof(HttpFunction))]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequestData req,
    FunctionContext executionContext)
{
    var logger = executionContext.GetLogger(nameof(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;
}

Registrazione

In .NET isolato è possibile scrivere nei log usando un'istanza ILogger<T> o ILogger . Il logger può essere ottenuto tramite l'inserimento delle dipendenze di un ILogger<T> oggetto o di un oggetto ILoggerFactory:

public class MyFunction {
    
    private readonly ILogger<MyFunction> _logger;
    
    public MyFunction(ILogger<MyFunction> logger) {
        _logger = logger;
    }
    
    [Function(nameof(MyFunction))]
    public void Run([BlobTrigger("samples-workitems/{name}", Connection = "")] string myBlob, string name)
    {
        _logger.LogInformation($"C# Blob trigger function Processed blob\n Name: {name} \n Data: {myBlob}");
    }

}

Il logger può anche essere ottenuto da un oggetto FunctionContext passato alla funzione. Chiamare il metodo GetLogger T> o GetLogger<, passando un valore stringa che corrisponde al nome della categoria in cui vengono scritti i log. La categoria è in genere il nome della funzione specifica da cui vengono scritti i log. Per altre informazioni sulle categorie, vedere l'articolo sul monitoraggio.

Usare i metodi di e ILogger per scrivere vari livelli di ILogger<T> log, ad esempio LogWarning o LogError. Per altre informazioni sui livelli di log, vedere l'articolo sul monitoraggio. È possibile personalizzare i livelli di log per i componenti aggiunti al codice registrando i filtri come parte della HostBuilder configurazione:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services =>
    {
        // Registers IHttpClientFactory.
        // By default this sends a lot of Information-level logs.
        services.AddHttpClient();
    })
    .ConfigureLogging(logging =>
    {
        // Disable IHttpClientFactory Informational logs.
        // Note -- you can also remove the handler that does the logging: https://github.com/aspnet/HttpClientFactory/issues/196#issuecomment-432755765 
        logging.AddFilter("System.Net.Http.HttpClient", LogLevel.Warning);
    })
    .Build();

Come parte della configurazione dell'app in Program.cs, è anche possibile definire il comportamento per la modalità di visualizzazione degli errori nei log. Per impostazione predefinita, le eccezioni generate dal codice possono finire incapsulate in un oggetto RpcException. Per rimuovere questo livello aggiuntivo, impostare la EnableUserCodeException proprietà su "true" come parte della configurazione del generatore:

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(builder => {}, options =>
    {
        options.EnableUserCodeException = true;
    })
    .Build();

Application Insights

È possibile configurare l'applicazione del processo isolato per generare log direttamente in Application Insights. Questo comportamento sostituisce il comportamento predefinito dell'inoltro dei log tramite l'host ed è consigliato perché consente di controllare come vengono generati tali log.

Installare i pacchetti

Per scrivere i log direttamente in Application Insights dal codice, aggiungere riferimenti a questi pacchetti nel progetto:

È possibile eseguire i comandi seguenti per aggiungere questi riferimenti al progetto:

dotnet add package Microsoft.ApplicationInsights.WorkerService
dotnet add package Microsoft.Azure.Functions.Worker.ApplicationInsights

Configurare l'avvio

Con i pacchetti installati, è necessario chiamare AddApplicationInsightsTelemetryWorkerService() e ConfigureFunctionsApplicationInsights() durante la Program.cs configurazione del servizio nel file, come in questo esempio:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
    
var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services => {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
    })
    .Build();

host.Run();

La chiamata a ConfigureFunctionsApplicationInsights() aggiunge un oggetto ITelemetryModule, che resta in ascolto di un oggetto Definito da ActivitySourceFunzioni. In questo modo vengono creati i dati di telemetria delle dipendenze necessari per supportare la traccia distribuita. Per altre informazioni e AddApplicationInsightsTelemetryWorkerService() su come usarlo, vedere Application Insights per le applicazioni del servizio di lavoro.

Gestione dei livelli di log

Importante

L'host funzioni e il ruolo di lavoro del processo isolato hanno una configurazione separata per i livelli di log e così via. Qualsiasi configurazione di Application Insights in host.json non influirà sulla registrazione dal ruolo di lavoro e, analogamente, la configurazione eseguita nel codice del ruolo di lavoro non influirà sulla registrazione dall'host. È necessario applicare le modifiche in entrambe le posizioni se lo scenario richiede la personalizzazione in entrambi i livelli.

Il resto dell'applicazione continua a funzionare con ILogger e ILogger<T>. Tuttavia, per impostazione predefinita, l’SDK Application Insights aggiunge un filtro del registro che indica al logger di acquisire solo avvisi e log più gravi. Se si vuole disabilitare questo comportamento, rimuovere la regola di filtro come parte della configurazione del servizio:

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services => {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
    })
    .ConfigureLogging(logging =>
    {
        logging.Services.Configure<LoggerFilterOptions>(options =>
        {
            LoggerFilterRule defaultRule = options.Rules.FirstOrDefault(rule => rule.ProviderName
                == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
            if (defaultRule is not null)
            {
                options.Rules.Remove(defaultRule);
            }
        });
    })
    .Build();

host.Run();

Ottimizzazioni delle prestazioni

Questa sezione illustra le opzioni che è possibile abilitare per migliorare le prestazioni relative all'avvio a freddo.

In generale, l'app deve usare le versioni più recenti delle relative dipendenze principali. Come minimo, è necessario aggiornare il progetto nel modo seguente:

  1. Aggiornare Microsoft.Azure.Functions.Worker alla versione 1.19.0 o successiva.
  2. Aggiornare Microsoft.Azure.Functions.Worker.Sdk alla versione 1.16.4 o successiva.
  3. Aggiungere un riferimento al framework a , a meno che l'app non sia destinata a Microsoft.AspNetCore.App.NET Framework.

Il frammento di codice seguente illustra questa configurazione nel contesto di un file di progetto:

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.16.4" />
  </ItemGroup>

Segnaposto

I segnaposto sono una funzionalità della piattaforma che migliora l'avvio a freddo per le app destinate a .NET 6 o versioni successive. Per usare questa ottimizzazione, è necessario abilitare in modo esplicito i segnaposto seguendo questa procedura:

  1. Aggiornare la configurazione del progetto per usare le versioni delle dipendenze più recenti, come descritto nella sezione precedente.

  2. Impostare l'impostazione dell'applicazione WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED su 1, che è possibile eseguire usando questo comando az functionapp config appsettings set :

    az functionapp config appsettings set -g <groupName> -n <appName> --settings 'WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED=1'
    

    In questo esempio sostituire <groupName> con il nome del gruppo di risorse e sostituire <appName> con il nome dell'app per le funzioni.

  3. Assicurarsi che la netFrameworkVersion proprietà dell'app per le funzioni corrisponda al framework di destinazione del progetto, che deve essere .NET 6 o versione successiva. A tale scopo, usare questo comando az functionapp config set :

    az functionapp config set -g <groupName> -n <appName> --net-framework-version <framework>
    

    In questo esempio sostituire anche <framework> con la stringa di versione appropriata, ad esempio v8.0, v7.0o v6.0, in base alla versione di .NET di destinazione.

  4. Assicurarsi che l'app per le funzioni sia configurata per l'uso di un processo a 64 bit, che è possibile eseguire usando questo comando az functionapp config set :

    az functionapp config set -g <groupName> -n <appName> --use-32bit-worker-process false
    

Importante

Quando si imposta su WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED1, tutte le altre configurazioni dell'app per le funzioni devono essere impostate correttamente. In caso contrario, l'app per le funzioni potrebbe non essere avviata.

Executor ottimizzato

L'executor della funzione è un componente della piattaforma che causa l'esecuzione delle chiamate. Una versione ottimizzata di questo componente è abilitata per impostazione predefinita a partire dalla versione 1.16.2 dell'SDK. Non è necessaria alcuna configurazione aggiuntiva.

ReadyToRun

È possibile compilare l'app per le funzioni come file binari ReadyToRun. ReadyToRun è una forma di compilazione anticipata che può migliorare le prestazioni di avvio per ridurre l'effetto degli avvii ad accesso sporadico durante l'esecuzione in un piano a consumo. ReadyToRun è disponibile in .NET 6 e versioni successive e richiede la versione 4.0 o successiva del runtime di Funzioni di Azure.

ReadyToRun richiede di compilare il progetto con l'architettura di runtime dell'app di hosting. Se non sono allineati, l'app visualizzerà un errore all'avvio. Selezionare l'identificatore di runtime da questa tabella:

Sistema operativo L'app è a 32 bit1 Identificatore di runtime
Windows Vero win-x86
Windows Falso win-x64
Linux Vero N/D (non supportato)
Linux Falso linux-x64

1 Solo le app a 64 bit sono idonee per altre ottimizzazioni delle prestazioni.

Per verificare se l'app di Windows è a 32 bit o a 64 bit, è possibile eseguire il comando dell'interfaccia della riga di comando seguente, sostituendo <group_name> con il nome del gruppo di risorse e <app_name> con il nome dell'applicazione. Un output "true" indica che l'app è a 32 bit e "false" indica 64 bit.

 az functionapp config show -g <group_name> -n <app_name> --query "use32BitWorkerProcess"

È possibile modificare l'applicazione a 64 bit con il comando seguente, usando le stesse sostituzioni:

az functionapp config set -g <group_name> -n <app_name> --use-32bit-worker-process false`

Per compilare il progetto come ReadyToRun, aggiornare il file di progetto aggiungendo gli <PublishReadyToRun> elementi e <RuntimeIdentifier> . L'esempio seguente illustra una configurazione per la pubblicazione in un'app per le funzioni a 64 bit di Windows.

<PropertyGroup>
  <TargetFramework>net8.0</TargetFramework>
  <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
  <PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>

Se non si vuole impostare come <RuntimeIdentifier> parte del file di progetto, è anche possibile configurare questa proprietà come parte del movimento di pubblicazione stesso. Ad esempio, con un'app per le funzioni a 64 bit windows, il comando dell'interfaccia della riga di comando di .NET sarà:

dotnet publish --runtime win-x64

In Visual Studio l'opzione Runtime di destinazione nel profilo di pubblicazione deve essere impostata sull'identificatore di runtime corretto. Se impostato sul valore predefinito di Portable, ReadyToRun non viene usato.

Distribuire in Funzioni di Azure

Quando si distribuisce il progetto di codice della funzione in Azure, deve essere eseguito in un'app per le funzioni o in un contenitore Linux. L'app per le funzioni e altre risorse di Azure necessarie devono esistere prima di distribuire il codice.

È anche possibile distribuire l'app per le funzioni in un contenitore Linux. Per altre informazioni, vedere Uso di contenitori e Funzioni di Azure.

Creare risorse Azure

È possibile creare l'app per le funzioni e altre risorse necessarie in Azure usando uno di questi metodi:

  • Visual Studio: Visual Studio può creare automaticamente risorse durante il processo di pubblicazione del codice.
  • Visual Studio Code: Visual Studio Code può connettersi alla sottoscrizione, creare le risorse necessarie per l'app e quindi pubblicare il codice.
  • Interfaccia della riga di comando di Azure: è possibile usare l'interfaccia della riga di comando di Azure per creare le risorse necessarie in Azure.
  • Azure PowerShell: è possibile usare Azure PowerShell per creare le risorse necessarie in Azure.
  • Modelli di distribuzione: è possibile usare modelli arm e file Bicep per automatizzare la distribuzione delle risorse necessarie in Azure. Assicurarsi che il modello includa le impostazioni necessarie.
  • portale di Azure: è possibile creare le risorse necessarie nel portale di Azure.

Pubblicare un progetto di codice

Dopo aver creato l'app per le funzioni e altre risorse necessarie in Azure, è possibile distribuire il progetto di codice in Azure usando uno di questi metodi:

  • Visual Studio: distribuzione manuale semplice durante lo sviluppo.
  • Visual Studio Code: distribuzione manuale semplice durante lo sviluppo.
  • Funzioni di Azure Core Tools: distribuire il file di progetto dalla riga di comando.
  • Distribuzione continua: utile per la manutenzione continua, spesso in uno slot di staging.
  • Modelli di distribuzione: è possibile usare modelli arm o file Bicep per automatizzare le distribuzioni dei pacchetti.

Per altre informazioni, vedere Tecnologie di distribuzione in Funzioni di Azure.

Requisiti di distribuzione

Esistono alcuni requisiti per l'esecuzione di funzioni .NET nel modello di lavoro isolato in Azure, a seconda del sistema operativo:

  • FUNCTIONS_WORKER_RUNTIME deve essere impostato su un valore di dotnet-isolated.
  • netFrameworkVersion deve essere impostato sulla versione desiderata.

Quando si crea l'app per le funzioni in Azure usando i metodi nella sezione precedente, queste impostazioni obbligatorie vengono aggiunte automaticamente. Quando si creano queste risorse usando i modelli arm o i file Bicep per l'automazione, è necessario assicurarsi di impostarli nel modello.

Debug

Quando si esegue localmente usando Visual Studio o Visual Studio Code, è possibile eseguire il debug del progetto di lavoro isolato .NET come di consueto. Esistono tuttavia due scenari di debug che non funzionano come previsto.

Debug remoto con Visual Studio

Poiché l'app processo di lavoro isolato viene eseguita all'esterno del runtime di Funzioni, è necessario collegare il debugger remoto a un processo separato. Per altre informazioni sul debug con Visual Studio, vedere Debug remoto.

Debug quando la destinazione è .NET Framework

Se il progetto isolato è destinato a .NET Framework 4.8, l'ambito di anteprima corrente richiede passaggi manuali per abilitare il debug. Questi passaggi non sono necessari se si usa un altro framework di destinazione.

L'app deve iniziare con una chiamata a FunctionsDebugger.Enable(); come prima operazione. Ciò si verifica nel Main() metodo prima di inizializzare un HostBuilder. Il Program.cs file dovrebbe essere simile al seguente:

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();
        }
    }
}

Successivamente, è necessario collegarsi manualmente al processo usando un debugger .NET Framework. Visual Studio non esegue questa operazione automaticamente per il processo di lavoro isolato per le app .NET Framework e l'operazione "Avvia debug" deve essere evitata.

Nella directory del progetto (o nella relativa directory di output di compilazione) eseguire:

func host start --dotnet-isolated-debug

Viene avviato il ruolo di lavoro e il processo viene arrestato con il messaggio seguente:

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

Dove <process id> è l'ID del processo di lavoro. È ora possibile usare Visual Studio per collegarsi manualmente al processo. Per istruzioni su questa operazione, vedere Come connettersi a un processo in esecuzione.

Dopo aver collegato il debugger, l'esecuzione del processo riprende e sarà possibile eseguire il debug.

Anteprima delle versioni di .NET

Prima di una versione disponibile a livello generale, una versione di .NET potrebbe essere rilasciata in uno stato di anteprima o live go. Per informazioni dettagliate su questi stati, vedere i criteri di supporto ufficiale di .NET.

Anche se potrebbe essere possibile specificare come destinazione una determinata versione da un progetto di Funzioni locale, le app per le funzioni ospitate in Azure potrebbero non avere tale versione disponibile. Funzioni di Azure possono essere usati solo con le versioni di anteprima o go live indicate in questa sezione.

Funzioni di Azure attualmente non funziona con le versioni .NET "Preview" o "Go-live". Vedere Versioni supportate per un elenco delle versioni disponibili a livello generale che è possibile usare.

Uso di un'anteprima di .NET SDK

Per usare Funzioni di Azure con una versione di anteprima di .NET, è necessario aggiornare il progetto in base a:

  1. Installazione della versione pertinente di .NET SDK nello sviluppo
  2. Modifica dell'impostazione TargetFramework nel .csproj file

Quando si esegue la distribuzione in un'app per le funzioni in Azure, è anche necessario assicurarsi che il framework sia reso disponibile per l'app. A tale scopo in Windows, è possibile usare il comando dell'interfaccia della riga di comando seguente. Sostituire <groupName> con il nome del gruppo di risorse e sostituire <appName> con il nome dell'app per le funzioni. Sostituire <framework> con la stringa di versione appropriata, ad esempio v8.0.

az functionapp config set -g <groupName> -n <appName> --net-framework-version <framework>

Considerazioni sull'uso delle versioni di anteprima di .NET

Tenere presenti queste considerazioni quando si usano Funzioni con versioni di anteprima di .NET:

  • Quando si creano le funzioni in Visual Studio, è necessario usare Visual Studio Preview, che supporta la compilazione di progetti Funzioni di Azure con gli SDK di anteprima .NET.

  • Assicurarsi di avere gli strumenti e i modelli di Funzioni più recenti. Per aggiornare gli strumenti:

    1. Passare a Opzioni strumenti>, scegliere Funzioni di Azure in Progetti e soluzioni.
    2. Selezionare Controlla aggiornamenti e installa gli aggiornamenti come richiesto.
  • Durante un periodo di anteprima, l'ambiente di sviluppo potrebbe avere una versione più recente dell'anteprima .NET rispetto al servizio ospitato. Ciò può causare l'esito negativo dell'app per le funzioni durante la distribuzione. Per risolvere questo problema, è possibile specificare la versione dell'SDK da usare in global.json.

    1. Eseguire il dotnet --list-sdks comando e prendere nota della versione di anteprima attualmente in uso durante lo sviluppo locale.
    2. Eseguire il dotnet new globaljson --sdk-version <SDK_VERSION> --force comando , dove <SDK_VERSION> è la versione in uso in locale. Ad esempio, dotnet new globaljson --sdk-version dotnet-sdk-8.0.100-preview.7.23376.3 --force fa sì che il sistema usi .NET 8 Preview 7 SDK durante la compilazione del progetto.

Nota

A causa del caricamento JIT dei framework di anteprima, le app per le funzioni in esecuzione in Windows possono riscontrare tempi di avvio a freddo maggiori rispetto alle versioni ga precedenti.

Passaggi successivi