Guida di riferimento per gli sviluppatori C# di Funzioni di AzureAzure Functions C# developer reference

Questo articolo è un'introduzione allo sviluppo di Funzioni di Azure tramite C# nelle librerie di classi .NET.This article is an introduction to developing Azure Functions by using C# in .NET class libraries.

Funzioni di Azure supporta i linguaggi di programmazione C# e script C#.Azure Functions supports C# and C# script programming languages. Per materiale sussidiario sull'uso di C# nel portale di Azure, vedere Guida di riferimento a per sviluppatori di script C# (.csx).If you're looking for guidance on using C# in the Azure portal, see C# script (.csx) developer reference.

Questo articolo presuppone che l'utente abbia già letto gli articoli seguenti:This article assumes that you've already read the following articles:

Progetto di libreria di classi per FunzioniFunctions class library project

In Visual Studio il modello di progetto Funzioni di Azure crea un progetto di libreria di classi C# contenente i file seguenti:In Visual Studio, the Azure Functions project template creates a C# class library project that contains the following files:

  • host.json: archivia le impostazioni di configurazione che interessano tutte le funzioni del progetto quando vengono eseguite nell'ambiente locale o in Azure.host.json - stores configuration settings that affect all functions in the project when running locally or in Azure.
  • local.settings.json: archivia le impostazioni dell'app e le stringhe di connessione usate per l'esecuzione nell'ambiente locale.local.settings.json - stores app settings and connection strings that are used when running locally.

Importante

Il processo di compilazione crea un file function.json per ogni funzione.The build process creates a function.json file for each function. Il file function.json non viene modificato direttamente.This function.json file is not meant to be edited directly. Non è possibile modificare la configurazione di associazione o disabilitare la funzione modificando il file.You can't change binding configuration or disable the function by editing this file. Per disabilitare una funzione, usare l'attributo il Disable.To disable a function, use the Disable attribute. Aggiungere ad esempio all'app l'impostazione booleana MY_TIMER_DISABLED e applicare [Disable("MY_TIMER_DISABLED")] alla funzione.For example, add a Boolean app setting MY_TIMER_DISABLED, and apply [Disable("MY_TIMER_DISABLED")] to your function. Sarà quindi possibile abilitarla e disabilitarla modificando l'impostazione dell'app.You can then enable and disable it by changing the app setting.

Metodi riconosciuti come funzioniMethods recognized as functions

In una libreria di classi, una funzione è un metodo statico con un attributo FunctionName e trigger, come illustrato nell'esempio seguente:In a class library, a function is a static method with a FunctionName and a trigger attribute, as shown in the following example:

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

L'attributo FunctionName indica il metodo come punto di ingresso della funzione.The FunctionName attribute marks the method as a function entry point. Il nome deve essere univoco nel progetto.The name must be unique within a project. I modelli di progetto spesso creano un metodo denominato Run, ma il nome del metodo può essere qualsiasi nome di metodo c# valido.Project templates often create a method named Run, but the method name can be any valid C# method name.

L'attributo trigger specifica il tipo di trigger e associa i dati di input a un parametro del metodo.The trigger attribute specifies the trigger type and binds input data to a method parameter. La funzione di esempio viene attivata da un messaggio della coda e il messaggio della coda viene passato al metodo nel parametro myQueueItem.The example function is triggered by a queue message, and the queue message is passed to the method in the myQueueItem parameter.

Parametri di Method SignatureMethod signature parameters

Method Signature può contenere parametri diversi da quelli usati con l'attributo trigger.The method signature may contain parameters other than the one used with the trigger attribute. Ecco alcuni dei parametri aggiuntivi che è possibile includere:Here are some of the additional parameters that you can include:

L'ordine dei parametri nella firma della funzione non è rilevante.The order of parameters in the function signature does not matter. È 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.For example, you can put trigger parameters before or after other bindings, and you can put the logger parameter before or after trigger or binding parameters.

Esempio di associazione di outputOutput binding example

L'esempio seguente differisce dal precedente per l'aggiunta di un'associazione di coda di output.The following example modifies the preceding one by adding an output queue binding. La funzione scrive il messaggio della coda che attiva la funzione in un nuovo messaggio di un'altra coda.The function writes the queue message that triggers the function to a new queue message in a different queue.

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

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.The binding reference articles (Storage queues, for example) explain which parameter types you can use with trigger, input, or output binding attributes.

Esempio di espressioni di associazioneBinding expressions example

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.The following code gets the name of the queue to monitor from an app setting, and it gets the queue message creation time in the insertionTime parameter.

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

Function.json generato automaticamenteAutogenerated function.json

Il processo di compilazione crea un file function.json in una cartella della funzione nella cartella di compilazione.The build process creates a function.json file in a function folder in the build folder. Come affermato in precedenza, questo file non viene modificato direttamente.As noted earlier, this file is not meant to be edited directly. Non è possibile modificare la configurazione di associazione o disabilitare la funzione modificando il file.You can't change binding configuration or disable the function by editing this file.

Lo scopo di questo file è fornire informazioni che il controller di scalabilità userà per decisioni di scalabilità nel piano a consumo.The purpose of this file is to provide information to the scale controller to use for scaling decisions on the consumption plan. Per questo motivo il file contiene solo informazioni di trigger, non associazioni di input o output.For this reason, the file only has trigger info, not input or output bindings.

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.The generated function.json file includes a configurationSource property that tells the runtime to use .NET attributes for bindings, rather than function.json configuration. Ad esempio:Here's an example:

{
  "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.FunctionsMicrosoft.NET.Sdk.Functions

La generazione del file function.json viene eseguita dal pacchetto NuGet Microsoft.NET.Sdk.Functions.The function.json file generation is performed by the NuGet package Microsoft.NET.Sdk.Functions.

Per le versioni 1.x e 2.x del runtime di Funzioni viene usato lo stesso pacchetto.The same package is used for both version 1.x and 2.x of the Functions runtime. Un progetto 1.x si distingue da un progetto 2.x in base al framework di destinazione.The target framework is what differentiates a 1.x project from a 2.x project. Ecco le parti rilevanti dei file con estensione csproj che mostrano i diversi framework di destinazione e lo stesso pacchetto Sdk:Here are the relevant parts of .csproj files, showing different target frameworks and the same Sdk package:

Funzioni 1.xFunctions 1.x

<PropertyGroup>
  <TargetFramework>net461</TargetFramework>
</PropertyGroup>
<ItemGroup>
  <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.8" />
</ItemGroup>

Funzioni 2.xFunctions 2.x

<PropertyGroup>
  <TargetFramework>netstandard2.0</TargetFramework>
  <AzureFunctionsVersion>v2</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
  <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.8" />
</ItemGroup>

Tra le dipendenze del pacchetto Sdk sono inclusi i trigger e le associazioni.Among the Sdk package dependencies are triggers and bindings. Un progetto 1.x fa riferimento a trigger e associazioni 1.x perché questi hanno come destinazione .NET Framework, mentre i trigger e le associazioni 2.x hanno come destinazione .NET Core.A 1.x project refers to 1.x triggers and bindings because those target the .NET Framework, while 2.x triggers and bindings target .NET Core.

Il pacchetto Sdk dipende inoltre da Newtonsoft.Json e indirettamente da WindowsAzure.Storage.The Sdk package also depends on Newtonsoft.Json, and indirectly on 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.These dependencies make sure that your project uses the versions of those packages that work with the Functions runtime version that the project targets. 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,For example, Newtonsoft.Json has version 11 for .NET Framework 4.6.1, but the Functions runtime that targets .NET Framework 4.6.1 is only compatible with Newtonsoft.Json 9.0.1. anche il codice delle funzioni nel progetto deve usare Newtonsoft.Json 9.0.1.So your function code in that project also has to use Newtonsoft.Json 9.0.1.

Il codice sorgente per Microsoft.NET.Sdk.Functions è disponibile nel repository GitHub azure-functions-vs-build-sdk.The source code for Microsoft.NET.Sdk.Functions is available in the GitHub repo azure-functions-vs-build-sdk.

Versione del runtimeRuntime version

Per eseguire i progetti di Funzioni, Visual Studio usa gli strumenti di base di Funzioni di Azure.Visual Studio uses the Azure Functions Core Tools to run Functions projects. Gli strumenti di base offrono un'interfaccia della riga di comando per il runtime di Funzioni.The Core Tools is a command-line interface for the Functions runtime.

Se si installano gli strumenti di base usando npm, questo non ha alcun effetto sulla versione degli strumenti di base usata da Visual Studio.If you install the Core Tools by using npm, that doesn't affect the Core Tools version used by 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.For the Functions runtime version 1.x, Visual Studio stores Core Tools versions in %USERPROFILE%\AppData\Local\Azure.Functions.Cli and uses the latest version stored there. Per Funzioni 2.x, gli strumenti di base sono inclusi nell'estensione Funzioni di Azure e strumenti per processi Web.For Functions 2.x, the Core Tools are included in the Azure Functions and Web Jobs Tools extension. Per entrambe le versioni 1.x e 2.x, è possibile vedere la versione in uso nell'output della console quando si esegue un progetto di Funzioni:For both 1.x and 2.x, you can see what version is being used in the console output when you run a Functions project:

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

Tipi supportati per le associazioniSupported types for bindings

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.Each binding has its own supported types; for instance, a blob trigger attribute can be applied to a string parameter, a POCO parameter, a CloudBlockBlob parameter, or any of several other supported types. L'articolo di riferimento sull'associazione relativo alle associazioni BLOB elenca tutti i tipi di parametri supportati.The binding reference article for blob bindings lists all supported parameter types. Per altre informazioni, vedere Trigger e associazioni e i documenti di riferimento per ogni tipo di associazione.For more information, see Triggers and bindings and the binding reference docs for each binding type.

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.If you plan to use the HTTP or WebHook bindings, plan to avoid port exhaustion that can be caused by improper instantiation of HttpClient. Per altre informazioni, vedere l'articolo Improper Instantiation antipattern (Antipattern non valido per la creazione di istanze).For more information, review the article Improper Instantiation antipattern.

Associazione al valore restituito dal metodoBinding to method return value

È possibile usare un valore restituito dal metodo per un'associazione di output applicando l'attributo a tale valore.You can use a method return value for an output binding, by applying the attribute to the method return value. Per alcuni esempi, vedere Trigger e associazioni.For examples, see Triggers and bindings.

Scrittura di più valori di outputWriting multiple output values

Per scrivere più valori in un'associazione di output, usare i tipi ICollector o IAsyncCollector .To write multiple values to an output binding, use the ICollector or IAsyncCollector types. Questi tipi sono raccolte di sola scrittura che vengono scritte nell'associazione di output durante il completamento del metodo.These types are write-only collections that are written to the output binding when the method completes.

Questo esempio scrive più messaggi in coda nella stessa coda usando ICollector:This example writes multiple queue messages into the same queue using ICollector:

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

RegistrazioneLogging

Per registrare l'output nei log in streaming in C#, includere un argomento di tipo TraceWriter.To log output to your streaming logs in C#, include an argument of type TraceWriter. È consigliabile denominarlo log.We recommend that you name it log. Evitare di usare Console.Write in Funzioni di Azure.Avoid using Console.Write in Azure Functions.

TraceWriter è definito in Azure WebJobs SDK.TraceWriter is defined in the Azure WebJobs SDK. Il livello di registrazione per TraceWriter può essere configurato in host.json.The log level for TraceWriter can be configured in host.json.

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

Nota

Per informazioni su un framework di registrazione più recente che è possibile usare al posto di TraceWriter, vedere Scrivere i log nelle funzioni C# nell'articolo Monitorare Funzioni di Azure.For information about a newer logging framework that you can use instead of TraceWriter, see Write logs in C# functions in the Monitor Azure Functions article.

AsyncAsync

Per rendere una funzione asincrona, usare la parola chiave async e restituire un oggetto Task.To make a function asynchronous, use the async keyword and return a Task object.

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,
        TraceWriter log)
    {
        log.Info($"BlobCopy function processed.");
        await blobInput.CopyToAsync(blobOutput, 4096, token);
    }
}

Token di annullamentoCancellation tokens

Una funzione può accettare un parametro CancellationToken, che consente al sistema operativo di notificare il codice quando la funzione sta per essere terminata.A function can accept a CancellationToken parameter, which enables the operating system to notify your code when the function is about to be terminated. È possibile usare questa notifica per assicurarsi che la funzione non termini in modo imprevisto lasciando i dati in uno stato incoerente.You can use this notification to make sure the function doesn't terminate unexpectedly in a way that leaves data in an inconsistent state.

L'esempio seguente illustra come verificare l'eventuale imminente interruzione della funzione.The following example shows how to check for impending function termination.

public static class CancellationTokenExample
{
    public static void Run(
        [QueueTrigger("inputqueue")] string inputText,
        TextWriter logger,
        CancellationToken token)
    {
        for (int i = 0; i < 100; i++)
        {
            if (token.IsCancellationRequested)
            {
                logger.WriteLine("Function was cancelled at iteration {0}", i);
                break;
            }
            Thread.Sleep(5000);
            logger.WriteLine("Normal processing for queue message={0}", inputText);
        }
    }
}

Variabili di ambienteEnvironment variables

Per ottenere una variabile di ambiente o un valore di impostazione dell'app, usare System.Environment.GetEnvironmentVariablecome illustrato nell'esempio di codice seguente:To get an environment variable or an app setting value, use System.Environment.GetEnvironmentVariable, as shown in the following code example:

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

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

Associazione in fase di esecuzioneBinding at runtime

In C# e altri linguaggi .NET, è possibile usare un modello di associazione imperativo anziché dichiarativo negli attributi.In C# and other .NET languages, you can use an imperative binding pattern, as opposed to the declarative bindings in attributes. L'associazione imperativa è utile quando i parametri di associazione devono essere calcolati in fase di runtime invece che in fase di progettazione.Imperative binding is useful when binding parameters need to be computed at runtime rather than design time. Con questo modello è possibile associare rapidamente i dati ad associazioni di input e output supportate nel codice della funzione.With this pattern, you can bind to supported input and output bindings on-the-fly in your function code.

Definire un'associazione imperativa, come segue:Define an imperative binding as follows:

  • Non includere un attributo nella firma della funzione per le associazioni imperative.Do not include an attribute in the function signature for your desired imperative bindings.
  • Passare un parametro di input Binder binder o IBinder binder.Pass in an input parameter Binder binder or IBinder binder.
  • Usare il seguente modello C# per eseguire l'associazione dati.Use the following C# pattern to perform the data binding.

    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.BindingTypeAttribute is the .NET attribute that defines your binding, and T is an input or output type that's supported by that binding type. T non può essere un tipo di parametro out, ad esempio out JObject.T cannot be an out parameter type (such as out JObject). L'associazione di output della tabella App per dispositivi mobili supporta ad esempio sei tipi di output, ma è possibile usare solo ICollector o IAsyncCollector con l'associazione imperativa.For example, the Mobile Apps table output binding supports six output types, but you can only use ICollector or IAsyncCollector with imperative binding.

Esempio con un solo attributoSingle attribute example

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.The following example code creates a Storage blob output binding with blob path that's defined at run time, then writes a string to the blob.

public static class IBinderExample
{
    [FunctionName("CreateBlobUsingBinder")]
    public static void Run(
        [QueueTrigger("myqueue-items-source-4")] string myQueueItem,
        IBinder binder,
        TraceWriter log)
    {
        log.Info($"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.BlobAttribute defines the Storage blob input or output binding, and TextWriter is a supported output binding type.

Esempio con più attributiMultiple attribute example

L'esempio precedente ottiene l'impostazione dell'app per la stringa di connessione dell'account di archiviazione principale dell'app, ovvero AzureWebJobsStorage.The preceding example gets the app setting for the function app's main Storage account connection string (which is 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>().You can specify a custom app setting to use for the Storage account by adding the StorageAccountAttribute and passing the attribute array into BindAsync<T>(). Usare un parametro Binder e non IBinder.Use a Binder parameter, not IBinder. Ad esempio: For example:

public static class IBinderExampleMultipleAttributes
{
    [FunctionName("CreateBlobInDifferentStorageAccount")]
    public async static Task RunAsync(
            [QueueTrigger("myqueue-items-source-binder2")] string myQueueItem,
            Binder binder,
            TraceWriter log)
    {
        log.Info($"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 associazioniTriggers and bindings

La tabella seguente elenca i trigger e gli attributi di associazione disponibili in un progetto di libreria di classi di Funzioni di Azure.The following table lists the trigger and binding attributes that are available in an Azure Functions class library project. Tutti gli attributi sono contenuti nello spazio dei nomi Microsoft.Azure.WebJobs.All attributes are in the namespace Microsoft.Azure.WebJobs.

TriggerTrigger InputInput OutputOutput
BlobTriggerBlobTrigger BLOBBlob BLOBBlob
CosmosDBTriggerCosmosDBTrigger DocumentDBDocumentDB DocumentDBDocumentDB
EventHubTriggerEventHubTrigger EventHubEventHub
HTTPTriggerHTTPTrigger
QueueTriggerQueueTrigger CodaQueue
ServiceBusTriggerServiceBusTrigger Bus di servizioServiceBus
TimerTriggerTimerTrigger
ApiHubFileApiHubFile ApiHubFileApiHubFile
MobileTableMobileTable MobileTableMobileTable
TabellaTable TabellaTable
NotificationHubNotificationHub
SendGridSendGrid
TwilioTwilio

Passaggi successiviNext steps