Esercitazione: Introduzione a Funzioni di Azure e Visual Studio per Mac

Importante

Visual Studio per Mac è prevista per il ritiro il 31 agosto 2024 in conformità con Microsoft Criteri moderni relativi al ciclo di vita. Anche se è possibile continuare a usare Visual Studio per Mac, esistono diverse altre opzioni per gli sviluppatori in Mac, ad esempio la versione di anteprima della nuova estensione C# Dev Kit per VS Code.

Altre informazioni sulle sequenze temporali e sulle alternative di supporto.

In questa esercitazione si apprenderà come iniziare a creare le funzioni di Azure tramite Visual Studio per Mac. Si integrerà anche con Archiviazione di Azure tabelle, che rappresentano uno dei molti tipi di associazioni e trigger disponibili per gli sviluppatori Funzioni di Azure.

Obiettivi

  • Creare ed eseguire il debug di funzioni di Azure locali
  • Integrazione con risorse Web e Archiviazione di Azure
  • Gestire un flusso di lavoro che interessa più funzioni di Azure

Requisiti

  • Visual Studio per Mac 7.5 o versione successiva.
  • Sottoscrizione di Azure (disponibile gratuitamente in https://azure.com/free).

Esercizio 1: Creazione di un progetto di Funzioni di Azure

  1. Avviare Visual Studio per Mac.

  2. Selezionare File > Nuova soluzione.

  3. Nella categoria Cloud > Generale selezionare il modello di Funzioni di Azure. Si userà C# per creare una libreria di classi .NET che ospita le funzioni di Azure. Fare clic su Avanti.

    Azure Functions template selection

  4. Impostare Nome progetto su "AzureFunctionsLab" e fare clic su Crea.

    naming and creating your Azure function project

  5. Espandere i nodi nella finestra della soluzione. Il modello di progetto predefinito include riferimenti NuGet a vari pacchetti di Processi Web di Azure e al pacchetto Newtonsoft.Json.

    Sono anche disponibili tre file: host.json per la descrizione delle opzioni di configurazione globale per l'host, local.settings.json per la configurazione delle impostazioni del servizio. Il modello di progetto crea anche un HttpTrigger predefinito. Ai fini di questa esercitazione, eliminare il file HttpTrigger.cs dal progetto.

    Aprire local.settings.json. Per impostazione predefinita il file include due impostazioni stringa di connessione vuote.

    solution window displaying local.settings.json file

Esercizio 2: Creazione di un account Archiviazione di Azure

  1. Accedere al proprio account Azure in https://portal.azure.com.

  2. Nella sezione Preferiti sul lato sinistro dello schermo, selezionare Account di archiviazione:

    favorites section of Azure portal showing storage accounts item

  3. Selezionare Aggiungi per creare un nuovo account di archiviazione:

    Button to add new storage account

  4. Immettere un nome univoco a livello globale in Nome e riusarlo per Gruppo di risorse. Mantenere i valori predefiniti per tutti gli altri elementi.

    new storage account details

  5. Fai clic su Crea. La creazione dell'account di archiviazione può richiedere alcuni minuti. Al completamento si riceve una notifica.

    deployment successful notification

  6. Selezionare il pulsante Vai alla risorsa nella notifica.

  7. Selezionare la scheda Chiavi di accesso.

    access key setting

  8. Copiare la prima stringa di connessione. Questa stringa viene usata per integrare Archiviazione di Azure con le funzioni di Azure in un secondo momento.

    information for key 1

  9. Tornare a Visual Studio per Mac e incollare la stringa di connessione completa nell'impostazione AzureWebJobsStorage in local.settings.json. Ora è possibile fare riferimento al nome dell'impostazione negli attributi per le funzioni che richiedono l'accesso alle risorse dell'impostazione.

    local settings file with connection key entered

Esempio 3: Creazione e debug di una funzione di Azure

  1. Ora è possibile iniziare ad aggiungere codice. Quando si usa una libreria di classi .NET le funzioni di Azure vengono aggiunte come metodi statici. Nella finestra della soluzione fare clic con il pulsante destro del mouse sul nodo del progetto AzureFunctions e scegliere Aggiungi > funzione:

    Add function option

  2. Nella finestra di dialogo Nuova funzione di Azure selezionare il modello webhook generico. Impostare Nome su Add e fare clic su Ok per creare una funzione:

    New Azure Functions dialog

  3. Nella parte superiore del nuovo file aggiungere le direttive using seguenti:

    using Microsoft.Azure.WebJobs.Extensions.Http;
    using System.Web;
    using Microsoft.WindowsAzure.Storage.Table;
    
  4. Rimuovere il metodo esistente Run e aggiungere il metodo seguente alla classe come funzione di Azure:

    [FunctionName("Add")]
    public static int Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]
    HttpRequestMessage req,
    TraceWriter log)
    {
        int x = 1;
        int y = 2;
    
        return x + y;
    }
    
  5. Di seguito si analizzano in dettaglio le varie sezioni della definizione del metodo.

    La prima cosa che si noterà è l'attributo FunctionName che contrassegna questo metodo come funzione di Azure. L'attributo specifica il nome pubblico della funzione. Il nome dell'attributo non deve necessariamente corrispondere al nome del metodo.

    New run method with FunctionName attribute highlighted

  6. Successivamente, il metodo è contrassegnato come metodo public static, impostazione necessaria. Si noterà anche che il valore restituito è un valore int. Se non diversamente specificato usando gli attributi del metodo, qualsiasi valore restituito non void di una funzione di Azure viene restituito al client come testo. Per impostazione predefinita viene restituito come XML, ma può essere modificato in JSON. Si eseguirà questa operazione più avanti nell'esercitazione.

    New run method with method initialization highlighted

  7. Il primo parametro è contrassegnato con l'attributo HttpTrigger, che indica che il metodo viene chiamato da una richiesta HTTP. L'attributo specifica anche il livello di autorizzazione del metodo, nonché i verbi supportati (in questo caso solo "GET"). Facoltativamente, è anche possibile definire una route che esegue l'override del percorso del metodo e offre un modo per estrarre automaticamente le variabili dal percorso. Dato che in questo caso l'impostazione Route è null, il percorso di questo metodo assume l'impostazione predefinita /api/Add.

    New run method with parameter highlighted

  8. Il parametro finale del metodo è un TraceWriter che può essere usato per registrare messaggi per errori e di diagnostica.

    New run method with TraceWriter highlighted

  9. Impostare un punto di interruzione sulla riga return del metodo facendo clic sul margine della riga:

    Breakpoint set at return line

  10. Compilare ed eseguire il progetto in una sessione di debug premendo F5 o selezionando Esegui avvia > debug. In alternativa è possibile scegliere pulsante Esegui. Tutte queste opzioni eseguono la stessa attività. Nel resto di questa esercitazione viene citato F5, ma è possibile usare il metodo che si preferisce.

    Build and Run project

  11. Quando si esegue il progetto, viene aperta automaticamente l'applicazione Terminale.

  12. Il progetto esegue un processo di rilevamento delle funzioni di Azure in base agli attributi del metodo e a una convenzione di file illustrata più avanti in questo articolo. In questo caso, rileva una singola funzione di Azure e "genera" 1 funzione del processo.

    Output of Azure function in Terminal

  13. Nella parte inferiore dei messaggi di avvio, l'host Funzioni di Azure visualizza gli URL delle eventuali API trigger HTTP. Dovrebbe essere presente un solo trigger. Copiare l'URL e incollarlo in una nuova scheda del browser.

    Azure function API URL

  14. Il punto di interruzione viene attivato immediatamente. La richiesta Web è stata inoltrata alla funzione e ora può essere sottoposta a debug. Portare il mouse sulla variabile x per visualizzarne il valore.

    Breakpoint triggered

  15. Rimuovere il punto di interruzione con lo stesso metodo usato in precedenza per aggiungerlo (fare clic sul margine o selezionare la riga e premere F9).

  16. Premere F5 per continuare con l'esecuzione.

  17. Nel browser viene visualizzato il risultato XML del metodo. Come previsto, l'operazione di addizione hardcoded produce una somma plausibile. Nota, se vedi solo "3" in Safari, vai a Safari Preferences Advanced e seleziona la casella di controllo "Mostra menu Sviluppo nella barra dei menu" e ricarica la > pagina.>

  18. In Visual Studio per Mac fare clic sul pulsante Arresta per terminare la sessione di debug. Per garantire che le nuove modifiche vengano implementate, ricordare di riavviare (arrestare e quindi eseguire) la sessione di debug.

    Stop debugging option

  19. Nel metodo Run sostituire le definizioni x e y con il codice seguente. Questo codice estrae valori dalla stringa di query dell'URL, per far sì che l'operazione di addizione sia eseguibile in modo dinamico in base ai parametri specificati.

    var query = HttpUtility.ParseQueryString(req.RequestUri.Query);
    
    int x = int.Parse(query["x"]);
    
    int y = int.Parse(query["y"]);
    
    return x + y;
    
  20. Eseguire l'applicazione.

  21. Tornare alla finestra del browser e aggiungere la stringa /?x=2&y=3 all'URL. L'URL intero ora sarà http://localhost:7071/api/Add?x=2&y=3. Passare al nuovo URL.

  22. Ora il risultato rifletterà i nuovi parametri. Eseguire il progetto con valori diversi. Non è disponibile nessun controllo degli errori, pertanto in caso di parametri non validi o mancanti viene generato un errore.

  23. Arrestare la sessione di debug.

Esercizio 4: Uso di function.json

  1. In un esercizio precedente è stato menzionato che Visual Studio per Mac "generata" una funzione di processo per la funzione di Azure definita nella libreria. Questo accade perché Funzioni di Azure non usa gli attributi del metodo in fase di runtime, ma usa una convenzione di file system in fase di compilazione per configurare la posizione e la modalità con cui le funzioni di Azure vengono rese disponibili. Nella finestra della soluzione fare clic con il pulsante destro del mouse sul nodo del progetto e scegliere Reveal in Finder.From the Solution Window, right-click on your project node and select Reveal in Finder.

    Reveal in Finder menu option

  2. Spostarsi verso il basso nel file system fino a raggiungere bin/Debug/netstandard2.0. Trovare la cartella Add. La cartella è stata creata per la corrispondenza con l'attributo del nome di funzione nel codice C#. Espandere la cartella Add per visualizzare un singolo file function.json. Questo file viene usato dal runtime per ospitare e gestire la funzione di Azure. Per altri modelli di linguaggio senza supporto in fase di compilazione (ad esempio script C# o JavaScript), queste cartelle devono essere create e gestite manualmente. Per gli sviluppatori C# vengono generate automaticamente dai metadati degli attributi in fase di compilazione. Fare clic con il pulsante destro del mouse su function.json e selezionare l'opzione che lo apre in Visual Studio.

    function.json in the file directory

  3. Tenendo in considerazione le fasi precedenti dell'esercitazione, ora si avrà un'idea di base degli attributi C#. Di conseguenza questo codice JSON dovrebbe risultare familiare. Tuttavia alcuni elementi non sono stati illustrati negli esercizi precedenti. Ad esempio, per ogni binding deve essere impostato l'elemento direction corrispondente. Come si può dedurre, "in" indica che il parametro è di input, mentre "out" indica che il parametro è un valore restituito (tramite $return) o un parametro out per il metodo. È anche necessario specificare l'elemento scriptFile (relativo a questo percorso finale) e il metodo entryPoint (public e static) all'interno dell'assembly. Nei passaggi seguenti si aggiungerà un percorso di funzione personalizzato usando questo modello. Copiare il contenuto di questo file negli Appunti.

    function.json file open in Visual Studio for mac

  4. Nella finestra della soluzione fare clic con il pulsante destro del mouse sul nodo del progetto AzureFunctionsLab e scegliere Aggiungi > nuova cartella. Assegnare il nome Adder alla nuova cartella. Per convenzione predefinita, il nome di questa cartella definisce il percorso dell'API, ad esempio api/Adder.

    New folder option

  5. Fare clic con il pulsante destro del mouse sulla cartella Adder e scegliere Aggiungi > nuovo file.

    New file option

  6. Selezionare la categoria Web e il modello File JSON vuoto. Impostare Nome su function e fare clic su Nuovo.

    Empty json file option

  7. Incollare il contenuto dell'altro file function.json (ottenuto nel passaggio 3) per sostituire il contenuto predefinito del file appena creato.

  8. Rimuovere le righe seguenti dalla parte iniziale del file con estensione json:

    "configurationSource":"attributes",
    "generatedBy":"Microsoft.NET.Sdk.Functions-1.0.13",
    
  9. Alla fine del primo binding (dopo la riga "name": "req"), aggiungere le proprietà seguenti. Non dimenticare di includere una virgola nella riga precedente. Questa proprietà sostituisce la radice predefinita e ora estrae i parametri int dal percorso e li inserisce nei parametri del metodo denominati x e y.

    "direction": "in",
    "route": "Adder/{x:int?}/{y:int?}"
    
  10. Aggiungere un altro binding sotto il primo. Questo binding gestisce il valore restituito della funzione. Non dimenticare di includere una virgola nella riga precedente:

    {
    "name": "$return",
    "type": "http",
    "direction": "out"
    }
    
  11. Aggiornare anche la proprietà entryPoint nella parte inferiore del file in modo che usi un metodo chiamato "Add2", come indicato di seguito. Lo scopo è dimostrare che il percorso api/Adder... può eseguire il mapping a un metodo appropriato con qualsiasi nome (in questo caso Add2).

    "entryPoint": "<project-name>.<function-class-name>.Add2"
    
  12. Il file function.json finale avrà un aspetto simile al seguente:

    {
    "bindings": [
        {
        "type": "httpTrigger",
        "methods": [
            "get"
        ],
        "authLevel": "function",
        "direction": "in",
        "name": "req",
        "route": "Adder/{x:int?}/{y:int?}"
        },
        {
        "name": "$return",
        "type": "http",
        "direction": "out"
        }
    ],
    "disabled": false,
    "scriptFile": "../bin/AzureFunctionsProject.dll",
    "entryPoint": "AzureFunctionsProject.Add.Add2"
    }
    
  13. Il passaggio finale necessario per attivare il funzionamento del progetto è un'istruzione che richiede a Visual Studio per Mac di copiare il file nello stesso percorso relativo della directory di output ogni volta che viene modificato. Con il file selezionato, scegliere la scheda delle proprietà sulla barra a destra, quindi in Copia nella directory di output selezionare Copia se più recente:

    Properties options for json file

  14. In Add.cs sostituire il metodo Run (incluso l'attributo) con il metodo seguente per completare la funzione prevista. Il metodo è molto simile a Run, ma non usa attributi e dispone di parametri espliciti per x e y.

    public static int Add2(
        HttpRequestMessage req,
        int x,
        int y,
        TraceWriter log)
    {
        return x + y;
    }
    
  15. Premere F5 per compilare ed eseguire il progetto.

  16. Dopo il completamento della compilazione e l'avvio della piattaforma, questa indica che è disponibile una seconda route per le richieste, mappata sul metodo appena aggiunto:

    URL for HTTP functions

  17. Tornare alla finestra del browser e passare a http://localhost:7071/api/Adder/3/5.

  18. Ora il metodo funziona di nuovo ed estrae parametri dal percorso, quindi produce una somma.

  19. Tornare a Visual Studio per Mac e terminare la sessione di debug.

Esercizio 5: Uso delle tabelle Archiviazione di Azure

Spesso, il servizio compilato potrebbe essere molto più complesso di quello creato finora e richiedere una notevole quantità di tempo o infrastruttura da eseguire. In questi casi può risultare utile accettare le richieste che vengono messe in coda per l'elaborazione quando le risorse diventano disponibili. Le funzioni di Azure supportano questo approccio. In altri casi, è consigliabile archiviare i dati centralmente. Le tabelle di Archiviazione di Azure consentono di eseguire questa operazione rapidamente.

  1. Aggiungere la classe seguente a Add.cs. La classe deve essere inserita all'interno dello spazio dei nomi, ma all'esterno della classe esistente.

    public class TableRow : TableEntity
    {
        public int X { get; set; }
        public int Y { get; set; }
        public int Sum { get; set; }
    }
    
  2. All'interno della classe Add aggiungere il codice seguente per introdurre un'altra funzione. Si noti che fino a questo punto il codice è univoco, in quanto non prevede una risposta HTTP. La riga finale restituisce un nuovo elemento TableRow completo di alcuni dati chiave che ne faciliteranno il recupero in una fase successiva (PartitionKey e RowKey), nonché dei relativi parametri e della somma. Anche il codice all'interno del metodo usa TraceWriter per facilitare il rilevamento dell'esecuzione della funzione.

    [FunctionName("Process")]
    [return: Table("Results")]
    public static TableRow Process(
        [HttpTrigger(AuthorizationLevel.Function, "get",
            Route = "Process/{x:int}/{y:int}")]
        HttpRequestMessage req,
        int x,
        int y,
        TraceWriter log)
    {
        log.Info($"Processing {x} + {y}");
    
        return new TableRow()
        {
            PartitionKey = "sums",
            RowKey = $"{x}_{y}",
            X = x,
            Y = y,
            Sum = x + y
        };
    }
    
  3. Premere F5 per compilare ed eseguire il progetto.

  4. Nella scheda del browser, passare a http://localhost:7071/api/Process/4/6. Questa operazione inserisce un altro messaggio nella coda, che a sua volta aggiungerà un'altra riga alla tabella in un secondo momento.

  5. Tornare a Terminal e verificare la richiesta in ingresso per 4 + 6.

    Terminal output showing addition request

  6. Tornare al browser per aggiornare la richiesta con lo stesso URL. Questa volta verrà visualizzato un errore dopo il metodo Process. Questo avviene perché il codice prova ad aggiungere una riga alla tabella di Archiviazione tabelle di Azure tramite una combinazione di partizione e chiave riga che esiste già.

    System.Private.CoreLib: Exception while executing function: Process. Microsoft.Azure.WebJobs.Host: Error while handling parameter $return after function returned:. Microsoft.Azure.WebJobs.Host: The specified entity already exists.

  7. Arrestare la sessione di debug.

  8. Per correggere l'errore, aggiungere il parametro seguente alla definizione del metodo, immediatamente prima del parametro TraceWriter. Questo parametro richiede alla piattaforma Funzioni di Azure di provare il recupero di una TableRow dalla tabella Results per la PartitionKey usata per l'archiviazione dei risultati. Tuttavia sarà sorprendente notare che RowKey viene generata dinamicamente in base agli altri parametri x e y per lo stesso metodo. Se tale riga esiste già, tableRow la includerà quando inizia l'esecuzione del metodo, senza richiedere lavoro aggiuntivo allo sviluppatore. Se la riga non esiste, il valore sarà null. Questo tipo di efficienza consente agli sviluppatori di concentrarsi sulla logica di business importante anziché sull'infrastruttura.

    [Table("Results", "sums", "{x}_{y}")]
    TableRow tableRow,
    
  9. Aggiungere il codice seguente all'inizio del metodo . Se tableRow non è null, i risultati per l'operazione richiesta sono già disponibili e possono essere restituiti immediatamente. In caso contrario, l'esecuzione della funzione continua come in precedenza. Anche se questo potrebbe non essere il modo più affidabile per restituire i dati, illustra il punto in cui è possibile orchestrare operazioni incredibilmente sofisticate in più livelli scalabili con codice molto piccolo.

    if (tableRow != null)
    {
        log.Info($"{x} + {y} already exists");
        return null;
    }
    
  10. Premere F5 per compilare ed eseguire il progetto.

  11. Nella scheda del browser, aggiornare l'URL in http://localhost:7071/api/Process/4/6. Dato che la riga della tabella per questo record esiste, viene restituita immediatamente e senza errori. Poiché non esiste alcun output HTTP, è possibile visualizzare l'output nel Terminale.

    Terminal output showing table row already exists

  12. Aggiornare l'URL in modo da riflettere una combinazione non ancora sottoposta a test, ad esempio http://localhost:7071/api/Process/5/7. Si noti il messaggio nel Terminale, indicante che la riga della tabella non è stata trovata (come previsto).

    Terminal output showing new process

  13. Tornare a Visual Studio per Mac e terminare la sessione di debug.

Riepilogo

In questa esercitazione si è appreso come iniziare a creare le funzioni di Azure tramite Visual Studio per Mac.