Tworzenie funkcji biblioteki klas języka C# przy użyciu usługi Azure Functions

Ten artykuł stanowi wprowadzenie do tworzenia usługi Azure Functions przy użyciu języka C# w bibliotekach klas platformy .NET.

Ważne

W tym artykule są obsługiwane funkcje biblioteki klas platformy .NET, które są uruchamiane w procesie w środowisku uruchomieniowym. Funkcje języka C# mogą również wyprowadzić proces i odizolować je od środowiska uruchomieniowego usługi Functions. Model izolowanego procesu roboczego to jedyny sposób uruchamiania wersji innych niż LTS aplikacji .NET i .NET Framework w bieżących wersjach środowiska uruchomieniowego usługi Functions. Aby dowiedzieć się więcej, zobacz Funkcje procesów procesu roboczego izolowanego platformy .NET. Aby zapoznać się z kompleksowym porównaniem procesu izolowanego procesu roboczego i funkcji platformy .NET w procesie, zobacz Różnice między procesem w procesie przetwarzania i izolowanym procesem roboczym platformy .NET Azure Functions.

Jako deweloper języka C# możesz również zainteresować się jednym z następujących artykułów:

Wprowadzenie Pojęcia Nauka z przewodnikiem/przykłady

Usługa Azure Functions obsługuje języki programowania skryptów w języku C# i C#. Jeśli szukasz wskazówek dotyczących korzystania z języka C# w witrynie Azure Portal, zobacz Dokumentację dla deweloperów skryptu języka C# (csx).

Obsługiwane wersje

Wersje środowiska uruchomieniowego usługi Functions obsługują określone wersje platformy .NET. Aby dowiedzieć się więcej na temat wersji usługi Functions, zobacz Omówienie wersji środowiska uruchomieniowego usługi Azure Functions. Obsługa wersji zależy również od tego, czy funkcje działają w procesie przetwarzania, czy izolowanego procesu roboczego.

Uwaga

Aby dowiedzieć się, jak zmienić wersję środowiska uruchomieniowego usługi Functions używaną przez aplikację funkcji, zobacz wyświetlanie i aktualizowanie bieżącej wersji środowiska uruchomieniowego.

W poniższej tabeli przedstawiono najwyższy poziom platformy .NET lub .NET Framework, który może być używany z określoną wersją usługi Functions.

Wersja środowiska uruchomieniowego usługi Functions Proces izolowanego procesu roboczego
(Izolowana platforma.NET)
Wewnątrz procesu
(Biblioteka klas platformy .NET)
Functions 4.x .NET 8.0
.NET 7.01
.NET 6.02
.NET Framework 4.83
.NET 6.02
Funkcje 1.x4 nie dotyczy .NET Framework 4.8

1 .NET 7 kończy oficjalne wsparcie 14 maja 2024 r.
2 .NET 6 kończy oficjalne wsparcie 12 listopada 2024 r.
3 Proces kompilacji wymaga również zestawu .NET 6 SDK.
4 Zakończenie wsparcia dla wersji 1.x środowiska uruchomieniowego usługi Azure Functions 14 września 2026 r. Aby uzyskać więcej informacji, zobacz to ogłoszenie pomocy technicznej. Aby zapewnić ciągłą pełną obsługę, należy przeprowadzić migrację aplikacji do wersji 4.x.

Aby uzyskać najnowsze informacje o wersjach usługi Azure Functions, w tym o usunięciu określonych starszych wersji pomocniczych, monitoruj ogłoszenia usługi aplikacja systemu Azure.

Projekt biblioteki klas usługi Functions

W programie Visual Studio szablon projektu usługi Azure Functions tworzy projekt biblioteki klas języka C#zawierający następujące pliki:

  • host.json — przechowuje ustawienia konfiguracji, które mają wpływ na wszystkie funkcje w projekcie podczas uruchamiania lokalnie lub na platformie Azure.
  • local.settings.json — przechowuje ustawienia aplikacji i parametry połączenia używane podczas lokalnego uruchamiania. Ten plik zawiera wpisy tajne i nie jest publikowany w aplikacji funkcji na platformie Azure. Zamiast tego dodaj ustawienia aplikacji do aplikacji funkcji.

Podczas kompilowania projektu struktura folderów, która wygląda jak w poniższym przykładzie, jest generowana w katalogu wyjściowym kompilacji:

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

Ten katalog jest wdrażany w aplikacji funkcji na platformie Azure. Rozszerzenia powiązań wymagane w wersji 2.x środowiska uruchomieniowego usługi Functions są dodawane do projektu jako pakiety NuGet.

Ważne

Proces kompilacji tworzy plik function.json dla każdej funkcji. Ten plik function.json nie ma być edytowany bezpośrednio. Nie można zmienić konfiguracji powiązania ani wyłączyć funkcji, edytując ten plik. Aby dowiedzieć się, jak wyłączyć funkcję, zobacz Jak wyłączyć funkcje.

Metody rozpoznawane jako funkcje

W bibliotece klas funkcja jest metodą z atrybutem FunctionName i wyzwalacza, jak pokazano w poniższym przykładzie:

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

Atrybut FunctionName oznacza metodę jako punkt wejścia funkcji. Nazwa musi być unikatowa w projekcie, zaczynać się literą i zawierać tylko litery, cyfry, _i -, do 127 znaków. Szablony projektów często tworzą metodę o nazwie Run, ale nazwa metody może być dowolną prawidłową nazwą metody języka C#. W powyższym przykładzie pokazano używaną metodę statyczną, ale funkcje nie muszą być statyczne.

Atrybut wyzwalacza określa typ wyzwalacza i wiąże dane wejściowe z parametrem metody. Przykładowa funkcja jest wyzwalana przez komunikat kolejki, a komunikat kolejki jest przekazywany do metody w parametrze myQueueItem .

Parametry sygnatury metody

Sygnatura metody może zawierać parametry inne niż używane z atrybutem wyzwalacza. Oto niektóre z innych parametrów, które można uwzględnić:

Kolejność parametrów w podpisie funkcji nie ma znaczenia. Można na przykład umieścić parametry wyzwalacza przed lub po innych powiązaniach i można umieścić parametr rejestratora przed wyzwalaczem lub po parametrach wyzwalacza lub powiązania.

Powiązania wyjściowe

Funkcja może mieć zero lub wiele powiązań wyjściowych zdefiniowanych przy użyciu parametrów wyjściowych.

Poniższy przykład modyfikuje poprzedni, dodając powiązanie kolejki wyjściowej o nazwie myQueueItemCopy. Funkcja zapisuje zawartość komunikatu, który wyzwala funkcję do nowego komunikatu w innej kolejce.

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

Wartości przypisane do powiązań wyjściowych są zapisywane po zakończeniu działania funkcji. W funkcji można użyć więcej niż jednego powiązania wyjściowego, przypisując po prostu wartości do wielu parametrów wyjściowych.

Artykuły referencyjne powiązań (na przykład kolejki usługi Storage) wyjaśniają typy parametrów, których można używać z atrybutami wyzwalacza, danych wejściowych lub wyjściowych powiązania.

Przykładowe wyrażenia powiązań

Poniższy kod pobiera nazwę kolejki do monitorowania z ustawienia aplikacji i pobiera czas tworzenia komunikatów kolejki w parametrze 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}");
    }
}

Automatycznie wygenerowany plik function.json

Proces kompilacji tworzy plik function.json w folderze funkcji w folderze kompilacji. Jak wspomniano wcześniej, ten plik nie ma być edytowany bezpośrednio. Nie można zmienić konfiguracji powiązania ani wyłączyć funkcji, edytując ten plik.

Celem tego pliku jest dostarczenie informacji kontrolerowi skalowania do użycia w celu podejmowania decyzji dotyczących skalowania planu Zużycie. Z tego powodu plik zawiera tylko informacje o wyzwalaczu, a nie powiązania wejściowe/wyjściowe.

Wygenerowany plik function.json zawiera configurationSource właściwość, która informuje środowisko uruchomieniowe o użyciu atrybutów platformy .NET dla powiązań, a nie konfiguracji function.json . Oto przykład:

{
  "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

Generowanie pliku function.json jest wykonywane przez pakiet NuGet Microsoft.NET.Sdk.Functions.

W poniższym przykładzie przedstawiono odpowiednie części .csproj plików, które mają różne struktury docelowe tego samego Sdk pakietu:

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

Sdk Wśród zależności pakietów są wyzwalacze i powiązania. Projekt w wersji 1.x odwołuje się do wyzwalaczy i powiązań 1.x, ponieważ te wyzwalacze i powiązania są przeznaczone dla platformy .NET Framework, podczas gdy wyzwalacze i powiązania w wersji 4.x dotyczą platformy .NET Core.

Pakiet Sdk zależy również od pliku Newtonsoft.Json i pośrednio w systemie WindowsAzure.Storage. Te zależności zapewniają, że projekt korzysta z wersji tych pakietów, które współpracują z wersją środowiska uruchomieniowego usługi Functions przeznaczoną dla projektu. Na przykład Newtonsoft.Json ma wersję 11 dla programu .NET Framework 4.6.1, ale środowisko uruchomieniowe usługi Functions przeznaczone dla programu .NET Framework 4.6.1 jest zgodne tylko z wersją Newtonsoft.Json 9.0.1. Dlatego kod funkcji w tym projekcie musi również używać Newtonsoft.Json wersji 9.0.1.

Kod źródłowy polecenia Microsoft.NET.Sdk.Functions jest dostępny w repozytorium GitHub azure-functions-vs-build-sdk.

Lokalna wersja środowiska uruchomieniowego

Program Visual Studio używa narzędzi Azure Functions Core Tools do uruchamiania projektów usługi Functions na komputerze lokalnym. Core Tools to interfejs wiersza polecenia dla środowiska uruchomieniowego usługi Functions.

Jeśli zainstalujesz narzędzia Core Tools przy użyciu pakietu Instalatora Windows (MSI) lub narzędzia npm, nie ma to wpływu na wersję narzędzi Core Tools używaną przez program Visual Studio. W przypadku środowiska uruchomieniowego usługi Functions w wersji 1.x program Visual Studio przechowuje wersje narzędzi Core Tools w folderze %USERPROFILE%\AppData\Local\Azure.Functions.Cli i używa najnowszej przechowywanej tam wersji. W przypadku usługi Functions 4.x narzędzia Core Tools znajdują się w rozszerzeniu Azure Functions i Web Jobs Tools . W przypadku usługi Functions 1.x można zobaczyć, jaka wersja jest używana w danych wyjściowych konsoli podczas uruchamiania projektu usługi Functions:

[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

Aplikację funkcji można skompilować jako pliki binarne ReadyToRun. ReadyToRun to forma kompilacji przed czasem, która może poprawić wydajność uruchamiania, aby zmniejszyć wpływ zimnego startu podczas uruchamiania w planie Zużycie.

Funkcja ReadyToRun jest dostępna na platformie .NET 6 i nowszych wersjach oraz wymaga wersji 4.0 środowiska uruchomieniowego usługi Azure Functions.

Aby skompilować projekt jako ReadyToRun, zaktualizuj plik projektu, dodając <PublishReadyToRun> elementy i <RuntimeIdentifier> . Poniżej przedstawiono konfigurację publikowania w aplikacji funkcji systemu Windows 32-bitowej.

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

Ważne

Począwszy od platformy .NET 6, dodano obsługę kompilacji Composite ReadyToRun. Zapoznaj się z ograniczeniami dotyczącymi platformy ReadyToRun Cross platform i architektury.

Możesz również skompilować aplikację za pomocą funkcji ReadyToRun z poziomu wiersza polecenia. Aby uzyskać więcej informacji, zobacz -p:PublishReadyToRun=true opcję w dotnet publishpliku .

Obsługiwane typy powiązań

Każde powiązanie ma własne obsługiwane typy; na przykład atrybut wyzwalacza obiektu blob można zastosować do parametru ciągu, parametru POCO, parametru CloudBlockBlob lub dowolnego z kilku innych obsługiwanych typów. W artykule referencyjnym dotyczącym powiązań obiektów blob wymieniono wszystkie obsługiwane typy parametrów . Aby uzyskać więcej informacji, zobacz Wyzwalacze i powiązania oraz dokumentację referencyjną powiązań dla każdego typu powiązania.

Napiwek

Jeśli planujesz używać powiązań HTTP lub WebHook, zaplanuj uniknięcie wyczerpania portów HttpClient, które mogą być spowodowane przez niewłaściwe utworzenie wystąpienia elementu . Aby uzyskać więcej informacji, zobacz Jak zarządzać połączeniami w usłudze Azure Functions.

Powiązanie z wartością zwracaną przez metodę

Możesz użyć wartości zwracanej metody dla powiązania wyjściowego, stosując atrybut do wartości zwracanej metody. Aby zapoznać się z przykładami, zobacz Wyzwalacze i powiązania.

Użyj wartości zwracanej tylko wtedy, gdy pomyślne wykonanie funkcji zawsze powoduje zwrócenie wartości do przekazania do powiązania wyjściowego. W przeciwnym razie użyj polecenia ICollector lub IAsyncCollector, jak pokazano w poniższej sekcji.

Zapisywanie wielu wartości wyjściowych

Aby zapisać wiele wartości w powiązaniu wyjściowym lub jeśli pomyślne wywołanie funkcji może nie spowodować przekazania niczego do powiązania wyjściowego, użyj ICollector typów lub IAsyncCollector . Te typy to kolekcje tylko do zapisu zapisywane w powiązaniu danych wyjściowych po zakończeniu działania metody.

W tym przykładzie wiele komunikatów kolejki jest zapisywanych w tej samej kolejce przy użyciu polecenia 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

Aby utworzyć funkcję asynchroniczną, użyj słowa kluczowego async i zwróć Task obiekt.

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

Nie można używać out parametrów w funkcjach asynchronicznych. W przypadku powiązań wyjściowych należy zamiast tego użyć wartości zwracanej funkcji lub obiektu modułu zbierającego.

Tokeny anulowania

Funkcja może akceptować parametr CancellationToken , który umożliwia systemowi operacyjnemu powiadamianie o kodzie po zakończeniu działania funkcji. Możesz użyć tego powiadomienia, aby upewnić się, że funkcja nie zostanie nieoczekiwanie zakończona w sposób, który pozostawia dane w stanie niespójnym.

Rozważ przypadek, gdy masz funkcję przetwarzającą komunikaty w partiach. Następująca funkcja wyzwalana przez usługę Azure Service Bus przetwarza tablicę obiektów ServiceBusReceivedMessage , która reprezentuje partię komunikatów przychodzących do przetworzenia przez wywołanie określonej funkcji:

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

Rejestrowanie

W kodzie funkcji można zapisywać dane wyjściowe w dziennikach, które są wyświetlane jako ślady w aplikacji Szczegółowe informacje. Zalecanym sposobem zapisu w dziennikach jest dołączenie parametru typu ILogger, który jest zwykle nazwany log. W wersji 1.x środowiska uruchomieniowego usługi Functions użyto TraceWriterpolecenia , który również zapisuje dane w usłudze Application Szczegółowe informacje, ale nie obsługuje rejestrowania strukturalnego. Nie używaj Console.Write funkcji do zapisywania dzienników, ponieważ te dane nie są przechwytywane przez aplikację Szczegółowe informacje.

ILogger

W definicji funkcji dołącz parametr ILogger , który obsługuje rejestrowanie strukturalne.

ILogger Obiekt wywołuje Log<level>metody rozszerzenia w usłudze ILogger w celu utworzenia dzienników. Poniższy kod zapisuje dzienniki Information z kategorią Function.<YOUR_FUNCTION_NAME>.User.:

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

Aby dowiedzieć się więcej o sposobie implementacji ILoggerusługi Functions, zobacz Zbieranie danych telemetrycznych. Kategorie poprzedzone Function założeniem ILogger , że używasz wystąpienia. Jeśli zdecydujesz się zamiast tego użyć ILogger<T>, nazwa kategorii może zamiast tego być oparta na .T

Rejestrowanie strukturalne

Kolejność symboli zastępczych, a nie ich nazw, określa, które parametry są używane w komunikacie dziennika. Załóżmy, że masz następujący kod:

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

Jeśli zachowasz ten sam ciąg komunikatu i odwrócisz kolejność parametrów, wynikowy tekst komunikatu będzie miał wartości w nieprawidłowych miejscach.

Symbole zastępcze są obsługiwane w ten sposób, aby można było wykonywać rejestrowanie strukturalne. Aplikacja Szczegółowe informacje przechowuje pary nazwa-wartość parametru i ciąg komunikatu. Wynikiem jest to, że argumenty komunikatu stają się polami, na których można wykonywać zapytania.

Jeśli wywołanie metody rejestratora wygląda jak w poprzednim przykładzie, możesz wykonać zapytanie względem pola customDimensions.prop__rowKey. Prefiks prop__ jest dodawany, aby upewnić się, że nie ma żadnych kolizji między polami, które dodaje środowisko uruchomieniowe, a polami dodanymi przez kod funkcji.

Możesz również wykonać zapytanie dotyczące oryginalnego ciągu komunikatu, odwołując się do pola customDimensions.prop__{OriginalFormat}.

Oto przykładowa reprezentacja customDimensions danych w formacie JSON:

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

Rejestrowanie telemetrii niestandardowej

Istnieje specyficzna dla funkcji wersja zestawu SDK usługi Application Szczegółowe informacje, której można użyć do wysyłania niestandardowych danych telemetrycznych z funkcji do usługi Application Szczegółowe informacje: Microsoft.Azure.WebJobs.Logging.Application Szczegółowe informacje. Użyj następującego polecenia w wierszu polecenia, aby zainstalować ten pakiet:

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

W tym poleceniu zastąp <VERSION> element wersją tego pakietu, która obsługuje zainstalowaną wersję zadań Microsoft.Azure.WebJobs.

W poniższych przykładach języka C# użyto niestandardowego interfejsu API telemetrii. Przykład dotyczy biblioteki klas platformy .NET, ale kod aplikacji Szczegółowe informacje jest taki sam dla skryptu języka C#.

Wersja 2.x i nowsze środowiska uruchomieniowego używają nowszych funkcji w aplikacji Szczegółowe informacje, aby automatycznie korelować dane telemetryczne z bieżącą operacją. Nie ma potrzeby ręcznego ustawiania operacji Id, ParentIdlub Name pól.

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

W tym przykładzie niestandardowe dane metryk są agregowane przez hosta przed wysłaniem ich do tabeli customMetrics. Aby dowiedzieć się więcej, zobacz dokumentację getmetric w aplikacji Szczegółowe informacje.

W przypadku uruchamiania lokalnego APPINSIGHTS_INSTRUMENTATIONKEY należy dodać ustawienie z kluczem Application Szczegółowe informacje do pliku local.settings.json.

Nie wywołujej wywołań TrackRequest ani StartOperation<RequestTelemetry> dlatego, że zobaczysz zduplikowane żądania wywołania funkcji. Środowisko uruchomieniowe usługi Functions automatycznie śledzi żądania.

Nie ustawiaj wartości telemetryClient.Context.Operation.Id. To ustawienie globalne powoduje nieprawidłową korelację, gdy wiele funkcji jest uruchomionych jednocześnie. Zamiast tego utwórz nowe wystąpienie telemetrii (DependencyTelemetry, EventTelemetry) i zmodyfikuj jego Context właściwość. Następnie przekaż wystąpienie telemetrii do odpowiedniej Track metody w dniu TelemetryClient (TrackDependency(), TrackEvent(), TrackMetric()). Ta metoda zapewnia, że dane telemetryczne mają poprawne szczegóły korelacji dla wywołania bieżącej funkcji.

Testowanie funkcji

W poniższych artykułach pokazano, jak uruchomić lokalnie funkcję biblioteki klas języka C# w procesie na potrzeby testowania:

Zmienne środowiskowe

Aby uzyskać zmienną środowiskową lub wartość ustawienia aplikacji, użyj metody System.Environment.GetEnvironmentVariable, jak pokazano w poniższym przykładzie kodu:

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

Ustawienia aplikacji można odczytywać ze zmiennych środowiskowych zarówno podczas programowania lokalnego, jak i podczas uruchamiania na platformie Azure. Podczas tworzenia aplikacji lokalnie ustawienia aplikacji pochodzą z Values kolekcji w pliku local.settings.json . W obu środowiskach, lokalnie i na platformie Azure pobiera GetEnvironmentVariable("<app setting name>") wartość nazwanego ustawienia aplikacji. Na przykład po uruchomieniu lokalnie zostanie zwrócona wartość "Moja nazwa witryny", jeśli plik local.settings.json zawiera { "Values": { "WEBSITE_SITE_NAME": "My Site Name" } }wartość .

Właściwość System.Configuration.ConfigurationManager.AppUstawienia jest alternatywnym interfejsem API do pobierania wartości ustawień aplikacji, ale zalecamy użycie goGetEnvironmentVariable, jak pokazano poniżej.

Wiązanie w czasie wykonywania

W języku C# i innych językach platformy .NET można użyć wzorca powiązania imperatywnego, w przeciwieństwie do powiązań deklaratywnych w atrybutach. Powiązanie imperatywne jest przydatne, gdy parametry powiązania muszą być obliczane w czasie wykonywania, a nie w czasie projektowania. Za pomocą tego wzorca można powiązać obsługiwane powiązania wejściowe i wyjściowe na bieżąco w kodzie funkcji.

Zdefiniuj powiązanie imperatywne w następujący sposób:

  • Nie dołączaj atrybutu do podpisu funkcji dla żądanych powiązań imperatywnych.

  • Przekaż parametr Binder binder wejściowy lub IBinder binder.

  • Użyj następującego wzorca języka C#, aby wykonać powiązanie danych.

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

    BindingTypeAttribute to atrybut platformy .NET, który definiuje powiązanie i T jest typem wejściowym lub wyjściowym obsługiwanym przez ten typ powiązania. T nie może być typem parametru out (takim jak out JObject). Na przykład powiązanie wyjściowe tabeli Mobile Apps obsługuje sześć typów danych wyjściowych, ale można użyć tylko metody ICollector T> lub IAsyncCollector<<T> z powiązaniem imperatywnym.

Przykład pojedynczego atrybutu

Poniższy przykładowy kod tworzy powiązanie wyjściowe obiektu blob usługi Storage ze ścieżką obiektu blob zdefiniowaną w czasie wykonywania, a następnie zapisuje ciąg w obiekcie 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!");
        };
    }
}

Obiekt BlobAttribute definiuje powiązanie wejściowe lub wyjściowe obiektu blob usługi Storage, a TextWriter jest obsługiwanym typem powiązania wyjściowego.

Przykład wielu atrybutów

Powyższy przykład pobiera ustawienie aplikacji dla głównego konta magazynu aplikacji funkcji parametry połączenia (czyli AzureWebJobsStorage). Możesz określić niestandardowe ustawienie aplikacji, które ma być używane dla konta magazynu, dodając atrybut StorageAccountAttribute i przekazując tablicę atrybutów do BindAsync<T>()elementu . Użyj parametru Binder , a nie IBinder. Na przykład:

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

Wyzwalacze i powiązania

W tej tabeli przedstawiono powiązania obsługiwane w głównych wersjach środowiska uruchomieniowego usługi Azure Functions:

Typ 1.x1 2.x i nowsze2 Wyzwalacz Dane wejściowe Dane wyjściowe
Blob Storage
Azure Cosmos DB
Azure Data Explorer
Azure SQL
Dapr4
Event Grid
Event Hubs
Http i elementy webhook
IoT Hub
Kafka3
Mobile Apps
Notification Hubs
Queue Storage
Redis
RabbitMQ3
SendGrid
Service Bus
SignalR
Table Storage
Czasomierz
Twilio

1Obsługa zakończy się w wersji 1.x środowiska uruchomieniowego usługi Azure Functions 14 września 2026 r. Zdecydowanie zalecamy przeprowadzenie migracji aplikacji do wersji 4.x w celu uzyskania pełnej pomocy technicznej.

2 Począwszy od środowiska uruchomieniowego w wersji 2.x, wszystkie powiązania z wyjątkiem protokołu HTTP i czasomierza muszą być zarejestrowane. Zobacz Rejestrowanie rozszerzeń powiązań.

3 Wyzwalacze nie są obsługiwane w planie Zużycie. Wymaga wyzwalaczy opartych na środowisku uruchomieniowym.

4 Obsługiwane tylko w rozwiązaniach Kubernetes, IoT Edge i innych trybach hostowanych samodzielnie.

Następne kroki