Sviluppare funzioni della libreria di classi C# usando Funzioni di Azure

Importante

Il supporto terminerà per il modello in-process il 10 novembre 2026. È consigliabile eseguire la migrazione delle app al modello di lavoro isolato per il supporto completo.

Questo articolo è un'introduzione allo sviluppo di Funzioni di Azure tramite C# nelle librerie di classi .NET. Queste librerie di classi vengono usate per l'esecuzione in-process con il runtime di Funzioni. Le funzioni .NET possono in alternativa eseguire _isolated dal runtime di Funzioni, che offre diversi vantaggi. Per altre informazioni, vedere il modello di lavoro isolato. Per un confronto completo tra questi due modelli, vedere Differenze tra il modello in-process e il modello di lavoro isolato.

Importante

Questo articolo supporta le funzioni della libreria di classi .NET eseguite in-process con il runtime. Le funzioni C# possono essere eseguite anche out-of-process e isolate dal runtime di Funzioni. Il modello di processo di lavoro isolato è l'unico modo per eseguire versioni non LTS delle app .NET e .NET Framework nelle versioni correnti del runtime di Funzioni. Per altre informazioni, vedere Funzioni del processo di lavoro isolato .NET. Per un confronto completo tra processi di lavoro isolati e funzioni .NET in-process, vedere Differenze tra processi in-process e isolare il processo di lavoro .NET Funzioni di Azure.

Gli sviluppatori C# possono anche essere interessati a uno degli articoli seguenti:

Introduzione Concetti Apprendimento guidato/esempi

Funzioni di Azure supporta i linguaggi di programmazione C# e script C#. Per materiale sussidiario sull'uso di C# nel portale di Azure, vedere Guida di riferimento a per sviluppatori di script C# (.csx).

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.

Progetto di libreria di classi per Funzioni

In Visual Studio il modello di progetto Funzioni di Azure crea un progetto di libreria di classi C# contenente i file seguenti:

  • host.json: archivia le impostazioni di configurazione che interessano tutte le funzioni del progetto quando vengono eseguite nell'ambiente locale o in Azure.
  • local.settings.json: archivia le impostazioni dell'app e le stringhe di connessione usate per l'esecuzione nell'ambiente locale. Questo file contiene segreti e non viene pubblicato nell'app per le funzioni in Azure. Aggiungere invece le impostazioni dell'app all'app per le funzioni.

Quando si compila il progetto, viene generata una struttura di cartelle simile all'esempio seguente nella directory di output della compilazione:

<framework.version>
 | - bin
 | - MyFirstFunction
 | | - function.json
 | - MySecondFunction
 | | - function.json
 | - host.json

Questa directory viene distribuita all'app per le funzioni in Azure. Le estensioni di associazione necessarie nella versione 2.x del runtime di Funzioni vengono aggiunte al progetto come pacchetti NuGet.

Importante

Il processo di compilazione crea un file function.json per ogni funzione. Il file function.json non viene modificato direttamente. Non è possibile modificare la configurazione di associazione o disabilitare la funzione modificando il file. Per informazioni su come disabilitare una funzione, vedere Come disabilitare le funzioni.

Metodi riconosciuti come funzioni

In una libreria di classi una funzione è un metodo con un FunctionName attributo trigger e , come illustrato nell'esempio seguente:

public static class SimpleExample
{
    [FunctionName("QueueTrigger")]
    public static void Run(
        [QueueTrigger("myqueue-items")] string myQueueItem, 
        ILogger log)
    {
        log.LogInformation($"C# function processed: {myQueueItem}");
    }
} 

L'attributo FunctionName 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. L'esempio precedente mostra un metodo statico usato, ma le funzioni non devono essere statiche.

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

Parametri di Method Signature

Method Signature può contenere parametri diversi da quelli usati con l'attributo trigger. Ecco alcuni degli altri parametri che è possibile includere:

L'ordine dei parametri nella firma della funzione non è rilevante. È ad esempio possibile inserire i parametri di trigger prima o dopo le altre associazioni e il parametro del logger prima o dopo i parametri di associazione o di trigger.

Associazioni di output

Una funzione può avere zero o più associazioni di output definite usando i parametri di output.

Nell'esempio seguente viene modificato quello precedente aggiungendo un'associazione di coda di output denominata myQueueItemCopy. La funzione scrive il contenuto del messaggio che attiva la funzione in un nuovo messaggio in una coda diversa.

public static class SimpleExampleWithOutput
{
    [FunctionName("CopyQueueMessage")]
    public static void Run(
        [QueueTrigger("myqueue-items-source")] string myQueueItem, 
        [Queue("myqueue-items-destination")] out string myQueueItemCopy,
        ILogger log)
    {
        log.LogInformation($"CopyQueueMessage function processed: {myQueueItem}");
        myQueueItemCopy = myQueueItem;
    }
}

I valori assegnati alle associazioni di output vengono scritti quando la funzione viene chiusa. È possibile usare più associazioni di output in una funzione semplicemente assegnando valori a più parametri di output.

Gli articoli di riferimento di associazione (Code di archiviazione, ad esempio) illustrano quali tipi di parametri è possibile usare con attributi di associazione di trigger, input o output.

Esempio di espressioni di associazione

Il codice seguente ottiene il nome della coda per il monitoraggio da un'impostazione di app e l'ora di creazione del messaggio della coda nel parametro insertionTime.

public static class BindingExpressionsExample
{
    [FunctionName("LogQueueMessage")]
    public static void Run(
        [QueueTrigger("%queueappsetting%")] string myQueueItem,
        DateTimeOffset insertionTime,
        ILogger log)
    {
        log.LogInformation($"Message content: {myQueueItem}");
        log.LogInformation($"Created at: {insertionTime}");
    }
}

Function.json generato automaticamente

Il processo di compilazione crea un file function.json in una cartella della funzione nella cartella di compilazione. Come indicato in precedenza, questo file non deve essere modificato direttamente. Non è possibile modificare la configurazione di associazione o disabilitare la funzione modificando il file.

Lo scopo di questo file è fornire informazioni al controller di scalabilità da usare per le decisioni di ridimensionamento nel piano a consumo. Per questo motivo, il file include solo informazioni sul trigger, non associazioni di input/output.

Il file function.json generato include una proprietà configurationSource che indica al runtime di usare gli attributi .NET per le associazioni invece della configurazione function.json. Ecco un esempio:

{
  "generatedBy": "Microsoft.NET.Sdk.Functions-1.0.0.0",
  "configurationSource": "attributes",
  "bindings": [
    {
      "type": "queueTrigger",
      "queueName": "%input-queue-name%",
      "name": "myQueueItem"
    }
  ],
  "disabled": false,
  "scriptFile": "..\\bin\\FunctionApp1.dll",
  "entryPoint": "FunctionApp1.QueueTrigger.Run"
}

Microsoft.NET.Sdk.Functions

La generazione di function.json file viene eseguita dal pacchetto NuGet Microsoft.NET.Sdk.Functions.

L'esempio seguente illustra le parti pertinenti dei .csproj file con framework di destinazione diversi dello stesso Sdk pacchetto:

<PropertyGroup>
  <TargetFramework>net6.0</TargetFramework>
  <AzureFunctionsVersion>v4</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
  <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.1" />
</ItemGroup>

Tra le dipendenze del pacchetto Sdk sono inclusi i trigger e le associazioni. Un progetto 1.x fa riferimento a trigger e associazioni 1.x perché tali trigger e associazioni sono destinati a .NET Framework, mentre i trigger e le associazioni 4.x sono destinati a .NET Core.

Il pacchetto Sdk dipende inoltre da Newtonsoft.Json e indirettamente da WindowsAzure.Storage. Queste dipendenze consentono di assicurarsi che il progetto usi le versioni dei pacchetti compatibili con la versione del runtime di Funzioni definita come destinazione del progetto. Se ad esempio è disponibile Newtonsoft.Json versione 11 per .NET Framework 4.6.1, ma il runtime di Funzioni che ha come destinazione .NET Framework 4.6.1 è compatibile solo con Newtonsoft.Json 9.0.1, anche il codice delle funzioni nel progetto deve usare Newtonsoft.Json 9.0.1.

Il codice sorgente per Microsoft.NET.Sdk.Functions è disponibile nel repository GitHub azure-functions-vs-build-sdk.

Versione del runtime locale

Visual Studio usa Funzioni di Azure Core Tools per eseguire progetti di Funzioni nel computer locale. Gli strumenti di base offrono un'interfaccia della riga di comando per il runtime di Funzioni.

Se si installa Core Tools usando il pacchetto Windows Installer (MSI) o tramite npm, non influisce sulla versione di Core Tools usata da Visual Studio. Per la versione 1.x del runtime di Funzioni, Visual Studio archivia le versioni degli strumenti di base in %USERPROFILE%\AppData\Local\Azure.Functions.Cli e usa la versione più recente archiviata. Per Funzioni 4.x, gli strumenti di base sono inclusi nell'estensione strumenti di Funzioni di Azure e processi Web. Per Funzioni 1.x, è possibile visualizzare la versione usata nell'output della console quando si esegue un progetto di Funzioni:

[3/1/2018 9:59:53 AM] Starting Host (HostId=contoso2-1518597420, Version=2.0.11353.0, ProcessId=22020, Debug=False, Attempt=0, FunctionsExtensionVersion=)

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'impatto dell'avvio sporadico durante l'esecuzione in un piano a consumo.

ReadyToRun è disponibile in .NET 6 e versioni successive e richiede la versione 4.0 del runtime di Funzioni di Azure.

Per compilare il progetto come ReadyToRun, aggiornare il file di progetto aggiungendo gli <PublishReadyToRun> elementi e <RuntimeIdentifier> . Di seguito è riportata la configurazione per la pubblicazione in un'app per le funzioni a 32 bit di Windows.

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

Importante

A partire da .NET 6, è stato aggiunto il supporto per la compilazione di ReadyToRun compositi. Vedere ReadyToRun Multipiattaforma e restrizioni dell'architettura.

È anche possibile compilare l'app con ReadyToRun dalla riga di comando. Per altre informazioni, vedere l'opzione -p:PublishReadyToRun=true in dotnet publish.

Tipi supportati per le associazioni

Ogni associazione supporta determinati tipi. Ad esempio è possibile applicare un attributo trigger di BLOB a un parametro stringa, un parametro POCO, un parametro CloudBlockBlob o uno dei molti altri tipi supportati. L'articolo di riferimento sull'associazione relativo alle associazioni BLOB elenca tutti i tipi di parametri supportati. Per altre informazioni, vedere Trigger e associazioni e i documenti di riferimento per ogni tipo di associazione.

Suggerimento

Se si prevede di usare binding HTTP o WebHook, evitare l'esaurimento delle porte che può essere causato da un'errata creazione di istanze di HttpClient. Per altre informazioni, vedere How to manage connections in Azure Functions (Come gestire le connessioni in Funzioni di Azure).

Associazione al valore restituito dal metodo

È possibile usare un valore restituito dal metodo per un'associazione di output applicando l'attributo a tale valore. Per alcuni esempi, vedere Trigger e associazioni.

Usare il valore restituito solo se la corretta esecuzione di una funzione restituisce sempre un valore da passare all'associazione di output. In caso contrario, usare ICollector o IAsyncCollector, come illustrato nella sezione seguente.

Scrittura di più valori di output

Per scrivere più valori in un'associazione di output o se una chiamata corretta alla funzione potrebbe non restituire alcun valore da passare all'associazione di output, usare i tipi ICollector o IAsyncCollector. Questi tipi sono raccolte di sola scrittura che vengono scritte nell'associazione di output durante il completamento del metodo.

Questo esempio scrive più messaggi in coda nella stessa coda usando ICollector:

public static class ICollectorExample
{
    [FunctionName("CopyQueueMessageICollector")]
    public static void Run(
        [QueueTrigger("myqueue-items-source-3")] string myQueueItem,
        [Queue("myqueue-items-destination")] ICollector<string> myDestinationQueue,
        ILogger log)
    {
        log.LogInformation($"C# function processed: {myQueueItem}");
        myDestinationQueue.Add($"Copy 1: {myQueueItem}");
        myDestinationQueue.Add($"Copy 2: {myQueueItem}");
    }
}

Async

Per rendere una funzione asincrona, usare la parola chiave async e restituire un oggetto Task.

public static class AsyncExample
{
    [FunctionName("BlobCopy")]
    public static async Task RunAsync(
        [BlobTrigger("sample-images/{blobName}")] Stream blobInput,
        [Blob("sample-images-copies/{blobName}", FileAccess.Write)] Stream blobOutput,
        CancellationToken token,
        ILogger log)
    {
        log.LogInformation($"BlobCopy function processed.");
        await blobInput.CopyToAsync(blobOutput, 4096, token);
    }
}

Non è possibile usare i parametri out in funzioni asincrone. Per le associazioni di output, usare invece il valore restituito di funzione o un oggetto agente di raccolta.

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.

Si consideri il caso in cui si dispone di una funzione che elabora i messaggi in batch. La funzione attivata dall'bus di servizio di Azure seguente elabora una matrice di oggetti ServiceBusReceivedMessage, che rappresenta un batch di messaggi in ingresso da elaborare da una chiamata di funzione specifica:

using Azure.Messaging.ServiceBus;
using System.Threading;

namespace ServiceBusCancellationToken
{
    public static class servicebus
    {
        [FunctionName("servicebus")]
        public static void Run([ServiceBusTrigger("csharpguitar", Connection = "SB_CONN")]
               ServiceBusReceivedMessage[] messages, CancellationToken cancellationToken, ILogger log)
        {
            try
            { 
                foreach (var message in messages)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        log.LogInformation("A cancellation token was received. Taking precautionary actions.");
                        //Take precautions like noting how far along you are with processing the batch
                        log.LogInformation("Precautionary activities --complete--.");
                        break;
                    }
                    else
                    {
                        //business logic as usual
                        log.LogInformation($"Message: {message} was processed.");
                    }
                }
            }
            catch (Exception ex)
            {
                log.LogInformation($"Something unexpected happened: {ex.Message}");
            }
        }
    }
}

Registrazione

Nel codice della funzione è possibile scrivere l'output nei log visualizzati come tracce in Application Insights. Il modo consigliato per scrivere nei log consiste nell'includere un parametro di tipo ILogger, che in genere è denominato log. La versione 1.x del runtime di Funzioni usata , TraceWriterche scrive anche in Application Insights, ma non supporta la registrazione strutturata. Non usare Console.Write per scrivere i log, poiché questi dati non vengono acquisiti da Application Insights.

ILogger

Nella definizione della funzione includere un parametro ILogger che supporta la registrazione strutturata.

Con un oggetto ILogger è possibile chiamare i metodi di estensione su ILoggerLog<level> per creare i log. Il codice seguente scrive Information i log con categoria Function.<YOUR_FUNCTION_NAME>.User.:

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, ILogger logger)
{
    logger.LogInformation("Request for item with key={itemKey}.", id);

Per altre informazioni su come funzioni implementa ILogger, vedere Raccolta di dati di telemetria. Le categorie con prefisso Function presuppongono che si stia usando un'istanza ILogger di . Se si sceglie di usare invece un oggetto ILogger<T>, il nome della categoria può invece essere basato su T.

Registrazione strutturata

I parametri usati nel messaggio del log sono determinati dall'ordine dei segnaposto, non dai nomi. Si supponga di avere il codice seguente:

string partitionKey = "partitionKey";
string rowKey = "rowKey";
logger.LogInformation("partitionKey={partitionKey}, rowKey={rowKey}", partitionKey, rowKey);

Se si mantenere la stessa stringa del messaggio e si inverte l'ordine dei parametri, il testo del messaggio risultante mostrerebbe i valori in maniera errata.

I segnaposto vengono gestiti in modo da poter eseguire la registrazione strutturata. Application Insights archivia le coppie nome-valore del parametro e la stringa del messaggio. Il risultato è che gli argomenti del messaggio diventano campi su cui è possibile eseguire delle query.

Se la chiamata al metodo del logger è simile all'esempio precedente, è possibile eseguire una query per il campo customDimensions.prop__rowKey. Il prefisso prop__ viene aggiunto per verificare che non ci siano conflitti tra i campi aggiunti dal runtime e i campi aggiunti dal codice funzione.

È anche possibile eseguire query sulla stringa del messaggio originale facendo riferimento al campo customDimensions.prop__{OriginalFormat}.

Ecco una rappresentazione JSON di esempio dei dati customDimensions:

{
  "customDimensions": {
    "prop__{OriginalFormat}":"C# Queue trigger function processed: {message}",
    "Category":"Function",
    "LogLevel":"Information",
    "prop__message":"c9519cbf-b1e6-4b9b-bf24-cb7d10b1bb89"
  }
}

Registrare dati di telemetria personalizzati

È disponibile una versione specifica di Funzioni di Application Insights SDK che è possibile usare per inviare dati di telemetria personalizzati dalle funzioni ad Application Insights: Microsoft.Azure.WebJobs.Logging.ApplicationInsights. Al prompt dei comandi, usare il comando seguente per installare il pacchetto:

dotnet add package Microsoft.Azure.WebJobs.Logging.ApplicationInsights --version <VERSION>

In questo comando sostituire <VERSION> con una versione del pacchetto che supporta la versione installata di Microsoft.Azure.WebJobs.

L'esempio C# seguente usa l'API di telemetria personalizzata. L'esempio fa riferimento a una libreria di classi .NET, ma il codice di Application Insights è lo stesso per lo script C#.

La versione 2.x e le versioni successive del runtime usano le funzionalità più recenti in Application Insights per correlare automaticamente i dati di telemetria con l'operazione corrente. Non è necessario impostare manualmente i campi Id, ParentId o Name dell'operazione.

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using System.Linq;

namespace functionapp0915
{
    public class HttpTrigger2
    {
        private readonly TelemetryClient telemetryClient;

        /// Using dependency injection will guarantee that you use the same configuration for telemetry collected automatically and manually.
        public HttpTrigger2(TelemetryConfiguration telemetryConfiguration)
        {
            this.telemetryClient = new TelemetryClient(telemetryConfiguration);
        }

        [FunctionName("HttpTrigger2")]
        public Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)]
            HttpRequest req, ExecutionContext context, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            DateTime start = DateTime.UtcNow;

            // Parse query parameter
            string name = req.Query
                .FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
                .Value;

            // Write an event to the customEvents table.
            var evt = new EventTelemetry("Function called");
            evt.Context.User.Id = name;
            this.telemetryClient.TrackEvent(evt);

            // Generate a custom metric, in this case let's use ContentLength.
            this.telemetryClient.GetMetric("contentLength").TrackValue(req.ContentLength);

            // Log a custom dependency in the dependencies table.
            var dependency = new DependencyTelemetry
            {
                Name = "GET api/planets/1/",
                Target = "swapi.co",
                Data = "https://swapi.co/api/planets/1/",
                Timestamp = start,
                Duration = DateTime.UtcNow - start,
                Success = true
            };
            dependency.Context.User.Id = name;
            this.telemetryClient.TrackDependency(dependency);

            return Task.FromResult<IActionResult>(new OkResult());
        }
    }
}

In questo esempio, i dati delle metriche personalizzate vengono aggregati dall'host prima di essere inviati alla tabella customMetrics. Per altre informazioni, vedere la documentazione di GetMetric in Application Insights.

Quando si esegue localmente, è necessario aggiungere l'impostazione APPINSIGHTS_INSTRUMENTATIONKEY , con la chiave di Application Insights, al file di local.settings.json .

Non chiamare TrackRequest o StartOperation<RequestTelemetry> poiché comparirebbero richieste duplicate per una chiamata di funzione. Il runtime di Funzioni rileva automaticamente le richieste.

Non impostare telemetryClient.Context.Operation.Id. Si tratta di un'impostazione globale che causa errori di correlazione quando molte funzioni vengono eseguite contemporaneamente. Creare invece una nuova istanza di telemetria (DependencyTelemetry, EventTelemetry) e modificare la relativa proprietà Context. Passare quindi l'istanza di telemetria al metodo Track corrispondente in TelemetryClient (TrackDependency(), TrackEvent(), TrackMetric()). Questo metodo assicura che la telemetria disponga dei dettagli di correlazione corretti per la chiamata di funzione corrente.

Test delle funzioni

Gli articoli seguenti illustrano come eseguire una funzione della libreria di classi C# in-process in locale a scopo di test:

Variabili di ambiente

Per ottenere una variabile di ambiente o un valore di impostazione dell'app, usare System.Environment.GetEnvironmentVariablecome illustrato nell'esempio di codice seguente:

public static class EnvironmentVariablesExample
{
    [FunctionName("GetEnvironmentVariables")]
    public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
    {
        log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
        log.LogInformation(GetEnvironmentVariable("AzureWebJobsStorage"));
        log.LogInformation(GetEnvironmentVariable("WEBSITE_SITE_NAME"));
    }

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

Le impostazioni dell'app possono essere lette dalle variabili di ambiente durante lo sviluppo in locale e durante l'esecuzione in Azure. Durante lo sviluppo in locale, le impostazioni dell'app vengono ricavate dalla raccolta Values nel file local.settings.json. In entrambi gli ambienti, locale e Azure, GetEnvironmentVariable("<app setting name>") recupera il valore dell'impostazione dell'app denominata. In caso di esecuzione locale, ad esempio, se il file local.settings.json contiene { "Values": { "WEBSITE_SITE_NAME": "My Site Name" } }, viene restituito "My Site Name".

La proprietà System.Configuration.ConfigurationManager.AppSettings è un'API alternativa per il recupero di valori di impostazione dell'app, ma è consigliabile usare GetEnvironmentVariable come illustrato di seguito.

Associazione in fase di esecuzione

In C# e altri linguaggi .NET, è possibile usare un modello di associazione imperativo anziché dichiarativo negli attributi. L'associazione imperativa è utile quando i parametri di associazione devono essere calcolati in fase di runtime invece che in fase di progettazione. Con questo modello è possibile associare rapidamente i dati ad associazioni di input e output supportate nel codice della funzione.

Definire un'associazione imperativa, come segue:

  • Non includere un attributo nella firma della funzione per le associazioni imperative.

  • Passare un parametro di input Binder binder o IBinder binder.

  • Usare il seguente modello C# per eseguire l'associazione dati.

    using (var output = await binder.BindAsync<T>(new BindingTypeAttribute(...)))
    {
        ...
    }
    

    BindingTypeAttribute è l'attributo .NET che definisce l'associazione e T è un tipo di input o output supportato da quel tipo di associazione. T non può essere un out tipo di parametro , ad esempio out JObject. Ad esempio, l'associazione di output della tabella di App per dispositivi mobili supporta sei tipi di output, ma è possibile usare solo ICollector<T> o IAsyncCollector<T> con binding imperativo.

Esempio con un solo attributo

L'esempio di codice seguente crea un associazione di output del BLOB di archiviazione con percorso del BLOB definito in fase di esecuzione, quindi scrive una stringa per il BLOB.

public static class IBinderExample
{
    [FunctionName("CreateBlobUsingBinder")]
    public static void Run(
        [QueueTrigger("myqueue-items-source-4")] string myQueueItem,
        IBinder binder,
        ILogger log)
    {
        log.LogInformation($"CreateBlobUsingBinder function processed: {myQueueItem}");
        using (var writer = binder.Bind<TextWriter>(new BlobAttribute(
                    $"samples-output/{myQueueItem}", FileAccess.Write)))
        {
            writer.Write("Hello World!");
        };
    }
}

BlobAttribute definisce l'associazione di input o output del BLOB di archiviazione e TextWriter è un tipo di associazione di output supportato.

Esempio di più attributi

L'esempio precedente ottiene l'impostazione dell'app per la stringa di connessione dell'account di archiviazione principale dell'app, ovvero AzureWebJobsStorage. È possibile specificare un'impostazione app personalizzata da usare per l'account di archiviazione aggiungendo StorageAccountAttribute e passando la matrice di attributi in BindAsync<T>(). Usare un parametro Binder e non IBinder. Ad esempio:

public static class IBinderExampleMultipleAttributes
{
    [FunctionName("CreateBlobInDifferentStorageAccount")]
    public async static Task RunAsync(
            [QueueTrigger("myqueue-items-source-binder2")] string myQueueItem,
            Binder binder,
            ILogger log)
    {
        log.LogInformation($"CreateBlobInDifferentStorageAccount function processed: {myQueueItem}");
        var attributes = new Attribute[]
        {
        new BlobAttribute($"samples-output/{myQueueItem}", FileAccess.Write),
        new StorageAccountAttribute("MyStorageAccount")
        };
        using (var writer = await binder.BindAsync<TextWriter>(attributes))
        {
            await writer.WriteAsync("Hello World!!");
        }
    }
}

Trigger e associazioni

Questa tabella mostra le associazioni supportate nelle versioni principali del runtime di Funzioni di Azure:

Type 1.x1 2.x e versioni successive2 Trigger Input Output
Archiviazione BLOB
Azure Cosmos DB
Esplora dati di Azure
Azure SQL
Dapr4
Griglia di eventi
Hub eventi
HTTP e webhook
Hub IoT
Kafka3
App per dispositivi mobili
Hub di notifica di Azure
Archiviazione code
Redis
RabbitMQ3
SendGrid
Bus di servizio
SignalR
Archiviazione tabelle
Timer
Twilio

1Il supporto terminerà per la versione 1.x del runtime Funzioni di Azure il 14 settembre 2026. È consigliabile eseguire la migrazione delle app alla versione 4.x per il supporto completo.

2 A partire dalla versione 2.x runtime, tutte le associazioni ad eccezione di HTTP e Timer devono essere registrate. Vedere Registrare le estensioni delle associazioni.

3 I trigger non sono supportati nel piano a consumo. Richiede trigger basati sul runtime.

4 Supportato solo in Kubernetes, IoT Edge e in altre modalità self-hosted.

Passaggi successivi