Dela via


Utveckla C#-klassbiblioteksfunktioner med hjälp av Azure Functions

Den här artikeln är en introduktion till att utveckla Azure Functions med hjälp av C# i .NET-klassbibliotek. Dessa klassbibliotek används för att köras i processen med Functions-körningen. Dina .NET-funktioner kan också köra _isolated från Functions-körningen, vilket ger flera fördelar. Mer information finns i den isolerade arbetsmodellen. En omfattande jämförelse mellan dessa två modeller finns i Skillnader mellan den processbaserade modellen och den isolerade arbetsmodellen.

Viktigt!

Den här artikeln stöder .NET-klassbiblioteksfunktioner som körs i processen med körningen. C#-funktionerna kan också köras utan process och isoleras från Functions-körningen. Den isolerade arbetsprocessmodellen är det enda sättet att köra icke-LTS-versioner av .NET- och .NET Framework-appar i aktuella versioner av Functions-körningen. Mer information finns i .NET-isolerade arbetsprocessfunktioner. En omfattande jämförelse mellan isolerade arbetsprocesser och processer i .NET Functions finns i Skillnader mellan processer och isolera arbetsprocess .NET Azure Functions.

Som C#-utvecklare kan du också vara intresserad av någon av följande artiklar:

Komma igång Begrepp Guidad utbildning/exempel

Azure Functions har stöd för programmeringsspråk för C# och C#-skript. Om du vill ha vägledning om hur du använder C# i Azure Portal läser du utvecklarreferensen för C#-skript (.csx).

Versioner som stöds

Versioner av Functions-körningen stöder specifika versioner av .NET. Mer information om Functions-versioner finns i Översikt över Azure Functions-körningsversioner. Versionsstöd beror också på om dina funktioner körs i en process eller en isolerad arbetsprocess.

Kommentar

Information om hur du ändrar den Functions-körningsversion som används av funktionsappen finns i Visa och uppdatera den aktuella körningsversionen.

I följande tabell visas den högsta nivån av .NET eller .NET Framework som kan användas med en specifik version av Functions.

Funktionskörningsversion Isolerad arbetsmodell Processmodell4
Funktioner 4.x1 .NET 9.0
.NET 8.0
.NET Framework 4.82
.NET 8.0
Funktioner 1.x3 saknas .NET Framework 4.8

1 .NET 6 hade tidigare stöd för båda modellerna men nådde slutet av det officiella stödet den 12 november 2024. .NET 7 hade tidigare stöd för den isolerade arbetsmodellen men nådde slutet av det officiella stödet den 14 maj 2024.

2 Byggprocessen kräver också .NET SDK.

3 Support upphör för version 1.x av Azure Functions-körningen den 14 september 2026. Mer information finns i det här supportmeddelandet. Om du vill ha fortsatt fullständigt stöd bör du migrera dina appar till version 4.x.

4 Supporten upphör för den pågående modellen den 10 november 2026. Mer information finns i det här supportmeddelandet. Om du vill ha fortsatt fullständigt stöd bör du migrera dina appar till den isolerade arbetsmodellen.

För de senaste nyheterna om Azure Functions-versioner, inklusive borttagning av specifika äldre mindre versioner, övervakar du Azure App Service-meddelanden.

Uppdatera till målet .NET 8

Appar som använder den processbaserade modellen kan rikta in sig på .NET 8 genom att följa stegen som beskrivs i det här avsnittet. Men om du väljer att använda det här alternativet bör du fortfarande börja planera migreringen till den isolerade arbetsmodellen innan supporten upphör för den pågående modellen den 10 november 2026.

Många appar kan ändra konfigurationen av funktionsappen i Azure utan uppdateringar av kod eller omdistribution. För att köra .NET 8 med den processbaserade modellen krävs tre konfigurationer:

  • Programinställningen FUNCTIONS_WORKER_RUNTIME måste anges med värdet "dotnet".
  • Programinställningen FUNCTIONS_EXTENSION_VERSION måste anges med värdet "~4".
  • Programinställningen FUNCTIONS_INPROC_NET8_ENABLED måste anges med värdet "1".
  • Du måste uppdatera stackkonfigurationen för att referera till .NET 8.

Stöd för .NET 8 använder fortfarande version 4.x av Functions-körningen och ingen ändring av den konfigurerade körningsversionen krävs.

Om du vill uppdatera ditt lokala projekt kontrollerar du först att du använder de senaste versionerna av lokala verktyg. Kontrollera sedan att projektet refererar till version 4.4.0 eller senare av Microsoft.NET.Sdk.Functions. Du kan sedan ändra TargetFramework till "net8.0". Du måste också uppdatera local.settings.json för att inkludera både FUNCTIONS_WORKER_RUNTIME inställt på "dotnet" och FUNCTIONS_INPROC_NET8_ENABLED inställt på "1".

Följande är ett exempel på en minimal project fil med dessa ändringar:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.4.0" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>

Följande är ett exempel på en minimal local.settings.json fil med dessa ändringar:

{
    "IsEncrypted": false,
    "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_INPROC_NET8_ENABLED": "1",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet"
    }
}

Om din app använder Microsoft.Azure.DurableTask.Netherite.AzureFunctionskontrollerar du att den är riktad mot version 1.5.3 eller senare. På grund av en beteendeförändring i .NET 8 utlöser appar med äldre versioner av paketet ett tvetydigt konstruktorfel.

Du kan behöva göra andra ändringar i din app baserat på versionsstöd för dess andra beroenden.

Version 4.x av Functions-körningen ger motsvarande funktioner för .NET 6 och .NET 8. Den processbaserade modellen innehåller inte ytterligare funktioner eller uppdateringar som integreras med nya .NET 8-funktioner. Körningen stöder till exempel inte nyckelade tjänster. Om du vill dra full nytta av de senaste .NET 8-funktionerna och förbättringarna måste du migrera till den isolerade arbetsmodellen.

Projekt för functions-klassbibliotek

I Visual Studio skapar Azure Functions-projektmallen ett C#-klassbiblioteksprojekt som innehåller följande filer:

  • host.json – lagrar konfigurationsinställningar som påverkar alla funktioner i projektet när de körs lokalt eller i Azure.
  • local.settings.json – lagrar appinställningar och anslutningssträng som används när de körs lokalt. Den här filen innehåller hemligheter och publiceras inte till din funktionsapp i Azure. Lägg i stället till appinställningar i funktionsappen.

När du skapar projektet genereras en mappstruktur som ser ut som i följande exempel i utdatakatalogen för bygget:

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

Den här katalogen är det som distribueras till din funktionsapp i Azure. Bindningstilläggen som krävs i version 2.x av Functions-körningen läggs till i projektet som NuGet-paket.

Viktigt!

Byggprocessen skapar en function.json fil för varje funktion. Den här function.json filen är inte avsedd att redigeras direkt. Du kan inte ändra bindningskonfigurationen eller inaktivera funktionen genom att redigera den här filen. Information om hur du inaktiverar en funktion finns i Inaktivera funktioner.

Metoder som identifieras som funktioner

I ett klassbibliotek är en funktion en metod med ett FunctionName och ett utlösarattribut, som du ser i följande exempel:

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

Attributet FunctionName markerar metoden som en funktionsinmatningspunkt. Namnet måste vara unikt i ett projekt, börja med en bokstav och endast innehålla bokstäver, siffror, _och -, upp till 127 tecken långa. Projektmallar skapar ofta en metod med namnet Run, men metodnamnet kan vara valfritt giltigt C#-metodnamn. Exemplet ovan visar en statisk metod som används, men funktioner krävs inte för att vara statiska.

Utlösarattributet anger utlösartypen och binder indata till en metodparameter. Exempelfunktionen utlöses av ett kömeddelande och kömeddelandet skickas till metoden i parametern myQueueItem .

Parametrar för metodsignatur

Metodsignaturen kan innehålla andra parametrar än den som används med utlösarattributet. Här är några av de andra parametrarna som du kan inkludera:

Ordningen på parametrarna i funktionssignaturen spelar ingen roll. Du kan till exempel sätta utlösarparametrar före eller efter andra bindningar och du kan placera loggerparametern före eller efter utlösare eller bindningsparametrar.

Utdatabindningar

En funktion kan ha noll- eller flera utdatabindningar definierade med hjälp av utdataparametrar.

I följande exempel ändras föregående genom att lägga till en utdataköbindning med namnet myQueueItemCopy. Funktionen skriver innehållet i meddelandet som utlöser funktionen till ett nytt meddelande i en annan kö.

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

Värden som tilldelas utdatabindningar skrivs när funktionen avslutas. Du kan använda mer än en utdatabindning i en funktion genom att helt enkelt tilldela värden till flera utdataparametrar.

I referensartiklarna för bindning (t.ex. lagringsköer) förklaras vilka parametertyper du kan använda med bindningsattribut för utlösare, indata eller utdata.

Exempel på bindningsuttryck

Följande kod hämtar namnet på kön som ska övervakas från en appinställning och hämtar tiden för att skapa kömeddelanden i parametern 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}");
    }
}

Automatiskt genererad function.json

Byggprocessen skapar en function.json fil i en funktionsmapp i byggmappen. Som tidigare nämnts är den här filen inte avsedd att redigeras direkt. Du kan inte ändra bindningskonfigurationen eller inaktivera funktionen genom att redigera den här filen.

Syftet med den här filen är att ge information till skalningskontrollanten som ska användas för skalningsbeslut i förbrukningsplanen. Därför har filen bara utlösarinformation, inte indata-/utdatabindningar.

Den genererade function.json-filen innehåller en configurationSource egenskap som talar om för körningen att använda .NET-attribut för bindningar i stället för function.json konfiguration. Här är ett exempel:

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

Den function.json filgenereringen utförs av NuGet-paketet Microsoft.NET.Sdk.Functions.

I följande exempel visas relevanta delar av .csproj filerna som har olika målramverk i samma Sdk paket:

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

Viktigt!

Från och med version 4.0.6517 av Core Tools måste processmodellprojekt referera till version 4.5.0 eller senare av Microsoft.NET.Sdk.Functions. Om en tidigare version används func start får kommandot fel.

Sdk Bland paketberoendena finns utlösare och bindningar. Ett 1.x-projekt refererar till 1.x-utlösare och bindningar eftersom dessa utlösare och bindningar riktar sig mot .NET Framework, medan 4.x-utlösare och bindningar riktar in sig på .NET Core.

Paketet Sdk beror också på Newtonsoft.Json och indirekt på WindowsAzure.Storage. Dessa beroenden ser till att projektet använder de versioner av paketen som fungerar med den Functions-körningsversion som projektet riktar in sig på. Har till exempel Newtonsoft.Json version 11 för .NET Framework 4.6.1, men Functions-körningen som riktar sig mot .NET Framework 4.6.1 är endast kompatibel med Newtonsoft.Json 9.0.1. Därför måste din funktionskod i projektet också använda Newtonsoft.Json 9.0.1.

Källkoden för Microsoft.NET.Sdk.Functions är tillgänglig i GitHub-lagringsplatsen azure-functions-vs-build-sdk.

Lokal körningsversion

Visual Studio använder Azure Functions Core Tools för att köra Functions-projekt på din lokala dator. Core Tools är ett kommandoradsgränssnitt för Functions-körningen.

Om du installerar Core Tools med windows installer-paketet (MSI) eller med hjälp av npm påverkar det inte den Core Tools-version som används av Visual Studio. För Functions-körningsversion 1.x lagrar Visual Studio Core Tools-versioner i %USERPROFILE%\AppData\Local\Azure.Functions.Cli och använder den senaste versionen som lagras där. För Functions 4.x ingår Core Tools i tillägget Azure Functions och Web Jobs Tools . För Functions 1.x kan du se vilken version som används i konsolutdata när du kör ett Functions-projekt:

[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

Du kan kompilera funktionsappen som ReadyToRun-binärfiler. ReadyToRun är en form av kompilering i förväg som kan förbättra startprestanda för att minska effekten av kallstart när du kör i en förbrukningsplan.

ReadyToRun är tillgängligt i .NET 6 och senare versioner och kräver version 4.0 av Azure Functions-körningen.

Om du vill kompilera projektet som ReadyToRun uppdaterar du projektfilen genom att lägga till elementen <PublishReadyToRun> och <RuntimeIdentifier> . Följande är konfigurationen för publicering till en Windows 32-bitars funktionsapp.

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

Viktigt!

Från och med .NET 6 har stöd för sammansatt ReadyToRun-kompilering lagts till. Kolla in Begränsningar för ReadyToRun Cross-plattform och arkitektur.

Du kan också skapa din app med ReadyToRun från kommandoraden. Mer information finns i alternativet -p:PublishReadyToRun=true i dotnet publish.

Typer som stöds för bindningar

Varje bindning har sina egna typer som stöds. Till exempel kan ett blobutlösarattribut tillämpas på en strängparameter, en POCO-parameter, en CloudBlockBlob parameter eller någon av flera andra typer som stöds. I artikeln med bindningsreferenser för blobbindningar visas alla parametertyper som stöds. Mer information finns i Utlösare och bindningar och bindningsreferensdokumenten för varje bindningstyp.

Dricks

Om du planerar att använda HTTP- eller WebHook-bindningarna planerar du att undvika portöverbelastning som kan orsakas av felaktig instansiering av HttpClient. Mer information finns i Hantera anslutningar i Azure Functions.

Bindning till metodens returvärde

Du kan använda ett metodreturvärde för en utdatabindning genom att tillämpa attributet på metodens returvärde. Exempel finns i Utlösare och bindningar.

Använd endast returvärdet om en lyckad funktionskörning alltid resulterar i ett returvärde som skickas till utdatabindningen. Annars använder du ICollector eller IAsyncCollector, som du ser i följande avsnitt.

Skriva flera utdatavärden

Om du vill skriva flera värden till en utdatabindning, eller om ett lyckat funktionsanrop kanske inte resulterar i något att skicka till utdatabindningen, använder du typerna ICollector eller IAsyncCollector . Dessa typer är skrivskyddade samlingar som skrivs till utdatabindningen när metoden är klar.

Det här exemplet skriver flera kömeddelanden i samma kö med hjälp av 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}");
    }
}

Asynkrona

Om du vill göra en funktion asynkron använder du nyckelordet async och returnerar ett Task objekt.

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

Du kan inte använda out parametrar i asynkrona funktioner. För utdatabindningar använder du funktionens returvärde eller ett insamlarobjekt i stället.

Annulleringstoken

En funktion kan acceptera parametern CancellationToken , vilket gör att operativsystemet kan meddela koden när funktionen är på väg att avslutas. Du kan använda det här meddelandet för att se till att funktionen inte avslutas oväntat på ett sätt som lämnar data i ett inkonsekvent tillstånd.

Tänk på fallet när du har en funktion som bearbetar meddelanden i batchar. Följande Azure Service Bus-utlösta funktion bearbetar en matris med ServiceBusReceivedMessage-objekt , som representerar en batch med inkommande meddelanden som ska bearbetas av en specifik funktionsanrop:

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

Loggning

I funktionskoden kan du skriva utdata till loggar som visas som spårningar i Application Insights. Det rekommenderade sättet att skriva till loggarna är att inkludera en parameter av typen ILogger, som vanligtvis heter log. Version 1.x av functions-körningen som används TraceWriter, som även skriver till Application Insights, men inte stöder strukturerad loggning. Använd Console.Write inte för att skriva dina loggar eftersom dessa data inte samlas in av Application Insights.

ILogger

I funktionsdefinitionen inkluderar du en ILogger-parameter som stöder strukturerad loggning.

Med ett ILogger objekt anropar Log<level> du tilläggsmetoder på ILogger för att skapa loggar. Följande kod skriver Information loggar med 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);

Mer information om hur Functions implementerar finns ILoggeri Samla in telemetridata. Kategorier som prefixet med Function förutsätter att du använder en ILogger instans. Om du väljer att i stället använda ett ILogger<T>kan kategorinamnet i stället baseras på T.

Strukturerad loggning

Platshållarnas ordning, inte deras namn, avgör vilka parametrar som används i loggmeddelandet. Anta att du har följande kod:

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

Om du behåller samma meddelandesträng och ändrar ordningen på parametrarna skulle den resulterande meddelandetexten ha värdena på fel platser.

Platshållare hanteras på det här sättet så att du kan utföra strukturerad loggning. Application Insights lagrar parameterns namn/värde-par och meddelandesträngen. Resultatet är att meddelandeargumenten blir fält som du kan fråga efter.

Om loggermetodanropet ser ut som i föregående exempel kan du fråga fältet customDimensions.prop__rowKey. Prefixet prop__ läggs till för att säkerställa att det inte finns några kollisioner mellan fält som runtime lägger till och fält som funktionskoden lägger till.

Du kan också fråga efter den ursprungliga meddelandesträngen genom att referera till fältet customDimensions.prop__{OriginalFormat}.

Här är en JSON-exempelrepresentation av customDimensions data:

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

Logga anpassad telemetri

Det finns en Funktionsspecifik version av Application Insights SDK som du kan använda för att skicka anpassade telemetridata från dina funktioner till Application Insights: Microsoft.Azure.WebJobs.Logging.ApplicationInsights. Använd följande kommando från kommandotolken för att installera det här paketet:

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

I det här kommandot ersätter du <VERSION> med en version av det här paketet som stöder din installerade version av Microsoft.Azure.WebJobs.

I följande C#-exempel används det anpassade telemetri-API:et. Exemplet är för ett .NET-klassbibliotek, men Application Insights-koden är densamma för C#-skriptet.

Version 2.x och senare versioner av körningen använder nyare funktioner i Application Insights för att automatiskt korrelera telemetri med den aktuella åtgärden. Du behöver inte ange åtgärden Id, ParentIdeller Name fälten manuellt.

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

I det här exemplet aggregeras anpassade måttdata av värden innan de skickas till tabellen customMetrics. Mer information finns i GetMetric-dokumentationen i Application Insights.

När du kör lokalt måste du lägga till APPINSIGHTS_INSTRUMENTATIONKEY inställningen med Application Insights-nyckeln i filen local.settings.json .

Anropa TrackRequest inte eller StartOperation<RequestTelemetry> för att du ser duplicerade begäranden för ett funktionsanrop. Functions-körningen spårar automatiskt begäranden.

Ställ inte in telemetryClient.Context.Operation.Id. Den här globala inställningen orsakar felaktig korrelation när många funktioner körs samtidigt. Skapa i stället en ny telemetriinstans (DependencyTelemetry, EventTelemetry) och ändra dess Context egenskap. Skicka sedan in telemetriinstansen till motsvarande Track metod på TelemetryClient (TrackDependency(), TrackEvent(), TrackMetric()). Den här metoden säkerställer att telemetrin har rätt korrelationsinformation för den aktuella funktionsanropet.

Testa funktioner

Följande artiklar visar hur du kör en processbaserad C#-klassbiblioteksfunktion lokalt i testsyfte:

Miljövariabler

Om du vill hämta en miljövariabel eller ett appinställningsvärde använder du System.Environment.GetEnvironmentVariable, som du ser i följande kodexempel:

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

Appinställningar kan läsas från miljövariabler både när du utvecklar lokalt och när de körs i Azure. När du utvecklar lokalt kommer appinställningarna från Values samlingen i local.settings.json-filen. I båda miljöerna, lokalt och Azure, GetEnvironmentVariable("<app setting name>") hämtar värdet för den namngivna appinställningen. När du till exempel kör lokalt returneras "Mitt webbplatsnamn" om din local.settings.json fil innehåller { "Values": { "WEBSITE_SITE_NAME": "My Site Name" } }.

Egenskapen System.Configuration.ConfigurationManager.AppSettings är ett alternativt API för att hämta appinställningsvärden , men vi rekommenderar att du använder GetEnvironmentVariable det som visas här.

Bindning vid körning

I C# och andra .NET-språk kan du använda ett imperativt bindningsmönster, till skillnad från deklarativa bindningar i attribut. Imperativ bindning är användbart när bindningsparametrar måste beräknas vid körning i stället för designtid. Med det här mönstret kan du binda till indata- och utdatabindningar som stöds direkt i funktionskoden.

Definiera en imperativ bindning enligt följande:

  • Inkludera inte ett attribut i funktionssignaturen för önskade imperativa bindningar.

  • Skicka in en indataparameter Binder binder eller IBinder binder.

  • Använd följande C#-mönster för att utföra databindningen.

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

    BindingTypeAttribute är .NET-attributet som definierar bindningen och T är en indata- eller utdatatyp som stöds av den bindningstypen. T kan inte vara en out parametertyp (till exempel out JObject). Till exempel stöder mobile apps-tabellutdatabindningen sex utdatatyper, men du kan bara använda ICollector<T> eller IAsyncCollector<T> med imperativ bindning.

Exempel på enstaka attribut

I följande exempelkod skapas en storage blob-utdatabindning med blobsökvägen som definieras vid körning och skriver sedan en sträng till bloben.

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 definierar bindningen för in- eller utdata för lagringsblob och TextWriter är en utdatabindningstyp som stöds.

Exempel på flera attribut

I föregående exempel hämtas appinställningen för funktionsappens huvudlagringskonto anslutningssträng (som är AzureWebJobsStorage). Du kan ange en anpassad appinställning som ska användas för lagringskontot genom att lägga till StorageAccountAttribute och skicka attributmatrisen till BindAsync<T>(). Använd en Binder parameter, inte IBinder. Till exempel:

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

Utlösare och bindningar

Den här tabellen visar bindningar som stöds i huvudversionerna av Azure Functions-körningen:

Typ 1.x1 2.x och högre2 Utlösare Indata Utdata
Blob Storage
Azure Cosmos DB
Azure-datautforskaren
Azure SQL
Dapr4
Event Grid
Event Hubs
HTTP & webhooks
IoT Hub
Kafka3
Mobile Apps
Notification Hubs
Queue Storage
Redis
RabbitMQ3
SendGrid
Service Bus
SignalR
Table Storage
Tidtagare
Twilio

Anteckningar:

  1. Supporten upphör för version 1.x av Azure Functions-körningen den 14 september 2026. Vi rekommenderar starkt att du migrerar dina appar till version 4.x för fullständig support.
  2. Från och med version 2.x-körningen måste alla bindningar utom HTTP och Timer registreras. Se Registrera bindningstillägg.
  3. Utlösare stöds inte i förbrukningsplanen. Kräver körningsdrivna utlösare.
  4. Stöds endast i Kubernetes, IoT Edge och andra lägen med egen värd.

Nästa steg