Desenvolver funções de biblioteca de classes C# usando o Azure Functions
Importante
O suporte para o modelo em processo terminará em 10 de novembro de 2026. É altamente recomendável que você migre seus aplicativos para o modelo de trabalho isolado para obter suporte total.
Este artigo é uma introdução ao desenvolvimento do Azure Functions usando C# em bibliotecas de classes .NET. Essas bibliotecas de classes são usadas para executar em processo com o tempo de execução do Functions. Alternativamente, suas funções .NET podem ser executadas _isolated a partir do tempo de execução do Functions, o que oferece várias vantagens. Para saber mais, consulte o modelo de trabalhador isolado. Para obter uma comparação abrangente entre esses dois modelos, consulte Diferenças entre o modelo em processo e o modelo de trabalhador isolado.
Importante
Este artigo suporta funções de biblioteca de classes .NET que são executadas em processo com o tempo de execução. Suas funções C# também podem ser executadas fora do processo e isoladas do tempo de execução do Functions. O modelo de processo de trabalho isolado é a única maneira de executar versões não-LTS de aplicativos .NET e .NET Framework em versões atuais do tempo de execução do Functions. Para saber mais, consulte Funções isoladas do processo de trabalho do .NET. Para obter uma comparação abrangente entre o processo de trabalho isolado e as funções .NET em processo, consulte Diferenças entre o processo de trabalho em processo e o processo de trabalho isolado .NET Azure Functions.
Como desenvolvedor C#, você também pode estar interessado em um dos seguintes artigos:
Introdução | Conceitos | Aprendizagem guiada/amostras |
---|---|---|
O Azure Functions suporta linguagens de programação de script C# e C#. Se você estiver procurando orientação sobre como usar C# no portal do Azure, consulte Referência do desenvolvedor do script C# (.csx).
Versões suportadas
As versões do tempo de execução do Functions suportam versões específicas do .NET. Para saber mais sobre as versões do Functions, consulte Visão geral das versões de tempo de execução do Azure Functions. O suporte à versão também depende se suas funções são executadas no processo ou no processo de trabalho isolado.
Nota
Para saber como alterar a versão de tempo de execução do Functions usada pelo seu aplicativo de função, consulte Exibir e atualizar a versão atual do tempo de execução.
A tabela a seguir mostra o nível mais alto de .NET ou .NET Framework que pode ser usado com uma versão específica do Functions.
Versão do tempo de execução do Functions | Modelo de trabalhador isolado | Modeloem processo 4 |
---|---|---|
Funções 4.x1 | .NET 9.0 .NET 8.0 .NET Framework 4.82 |
.NET 8.0 |
Funções 1.x3 | n/d | .NET Framework 4.8 |
1 O .NET 6 era anteriormente suportado em ambos os modelos, mas chegou ao fim do suporte oficial em 12 de novembro de 2024. O .NET 7 era anteriormente suportado no modelo de trabalhador isolado, mas chegou ao fim do suporte oficial em 14 de maio de 2024.
2 O processo de compilação também requer o SDK do .NET.
3 O suporte termina para a versão 1.x do tempo de execução do Azure Functions em 14 de setembro de 2026. Para obter mais informações, consulte este anúncio de suporte. Para obter suporte total contínuo, você deve migrar seus aplicativos para a versão 4.x.
4 O suporte para o modelo em processo termina em 10 de novembro de 2026. Para obter mais informações, consulte este anúncio de suporte. Para obter suporte total contínuo, você deve migrar seus aplicativos para o modelo de trabalho isolado.
Para obter as últimas notícias sobre as versões do Azure Functions, incluindo a remoção de versões secundárias mais antigas específicas, monitore os anúncios do Serviço de Aplicativo do Azure.
Atualizando para o .NET 8 de destino
Os aplicativos que usam o modelo em processo podem direcionar o .NET 8 seguindo as etapas descritas nesta seção. No entanto, se você optar por exercer essa opção, ainda deverá começar a planejar sua migração para o modelo de trabalhador isolado antes que o suporte termine para o modelo em processo em 10 de novembro de 2026.
Muitos aplicativos podem alterar a configuração do aplicativo de função no Azure sem atualizações de código ou reimplantação. Para executar o .NET 8 com o modelo em processo, são necessárias três configurações:
- A configuração
FUNCTIONS_WORKER_RUNTIME
do aplicativo deve ser definida com o valor "dotnet". - A configuração
FUNCTIONS_EXTENSION_VERSION
do aplicativo deve ser definida com o valor "~4". - A configuração
FUNCTIONS_INPROC_NET8_ENABLED
do aplicativo deve ser definida com o valor "1". - Você deve atualizar a configuração da pilha para fazer referência ao .NET 8.
O suporte para o .NET 8 ainda usa a versão 4.x do tempo de execução do Functions e nenhuma alteração na versão de tempo de execução configurada é necessária.
Para atualizar seu projeto local, primeiro verifique se você está usando as versões mais recentes das ferramentas locais. Em seguida, certifique-se de que o projeto faz referência à versão 4.4.0 ou posterior do Microsoft.NET.Sdk.Functions. Você pode então alterar o seu TargetFramework
para "net8.0". Você também deve atualizar local.settings.json
para incluir ambos FUNCTIONS_WORKER_RUNTIME
definidos como "dotnet" e FUNCTIONS_INPROC_NET8_ENABLED
definidos como "1".
Segue-se um exemplo de um ficheiro mínimo project
com estas alterações:
<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>
Segue-se um exemplo de um ficheiro mínimo local.settings.json
com estas alterações:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_INPROC_NET8_ENABLED": "1",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}
Se a sua aplicação utilizar Microsoft.Azure.DurableTask.Netherite.AzureFunctions
o , certifique-se de que se destina à versão 1.5.3 ou posterior. Devido a uma alteração de comportamento no .NET 8, os aplicativos com versões mais antigas do pacote lançarão uma exceção de construtor ambígua.
Talvez seja necessário fazer outras alterações em seu aplicativo com base no suporte de versão de suas outras dependências.
A versão 4.x do tempo de execução do Functions fornece funcionalidade equivalente para .NET 6 e .NET 8. O modelo em processo não inclui recursos adicionais ou atualizações que se integram aos novos recursos do .NET 8. Por exemplo, o tempo de execução não suporta serviços chaveados. Para aproveitar ao máximo os recursos e aprimoramentos mais recentes do .NET 8, você deve migrar para o modelo de trabalho isolado.
Projeto de biblioteca de classes Functions
No Visual Studio, o modelo de projeto do Azure Functions cria um projeto de biblioteca de classes C# que contém os seguintes arquivos:
- host.json - armazena definições de configuração que afetam todas as funções no projeto quando executado localmente ou no Azure.
- local.settings.json - armazena configurações de aplicativos e cadeias de conexão que são usadas quando executadas localmente. Este ficheiro contém segredos e não é publicado na sua aplicação de função no Azure. Em vez disso, adicione as configurações do aplicativo ao seu aplicativo de função.
Quando você cria o projeto, uma estrutura de pastas que se parece com o exemplo a seguir é gerada no diretório de saída da compilação:
<framework.version>
| - bin
| - MyFirstFunction
| | - function.json
| - MySecondFunction
| | - function.json
| - host.json
Esse diretório é o que é implantado em seu aplicativo de função no Azure. As extensões de vinculação necessárias na versão 2.x do tempo de execução do Functions são adicionadas ao projeto como pacotes NuGet.
Importante
O processo de compilação cria um arquivo de function.json para cada função. Este ficheiro function.json não se destina a ser editado diretamente. Não é possível alterar a configuração de vinculação ou desativar a função editando este arquivo. Para saber como desativar uma função, consulte Como desativar funções.
Métodos reconhecidos como funções
Em uma biblioteca de classes, uma função é um método com um FunctionName
atributo e um gatilho, conforme mostrado no exemplo a seguir:
public static class SimpleExample
{
[FunctionName("QueueTrigger")]
public static void Run(
[QueueTrigger("myqueue-items")] string myQueueItem,
ILogger log)
{
log.LogInformation($"C# function processed: {myQueueItem}");
}
}
O FunctionName
atributo marca o método como um ponto de entrada de função. O nome deve ser exclusivo dentro de um projeto, começar com uma letra e conter apenas letras, _
números e -
, até 127 caracteres de comprimento. Os modelos de projeto geralmente criam um método chamado Run
, mas o nome do método pode ser qualquer nome de método C# válido. O exemplo acima mostra um método estático sendo usado, mas as funções não precisam ser estáticas.
O atributo trigger especifica o tipo de gatilho e vincula os dados de entrada a um parâmetro de método. A função de exemplo é acionada por uma mensagem de fila e a mensagem de fila é passada para o método no myQueueItem
parâmetro.
Parâmetros de assinatura do método
A assinatura do método pode conter parâmetros diferentes daquele usado com o atributo trigger. Aqui estão alguns dos outros parâmetros que você pode incluir:
- Ligações de entrada e saída marcadas como tal, decorando-as com atributos.
- Um
ILogger
ouTraceWriter
(somente versão 1.x) parâmetro para registro. - Um
CancellationToken
parâmetro para o desligamento normal. - Vinculando parâmetros de expressões para obter metadados de gatilho.
A ordem dos parâmetros na assinatura da função não importa. Por exemplo, você pode colocar parâmetros de gatilho antes ou depois de outras associações e pode colocar o parâmetro do registrador antes ou depois dos parâmetros de gatilho ou vinculação.
Enlaces de saída
Uma função pode ter zero ou várias ligações de saída definidas usando parâmetros de saída.
O exemplo a seguir modifica o anterior adicionando uma ligação de fila de saída chamada myQueueItemCopy
. A função grava o conteúdo da mensagem que dispara a função para uma nova mensagem em uma fila diferente.
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;
}
}
Os valores atribuídos às ligações de saída são gravados quando a função é encerrada. Você pode usar mais de uma ligação de saída em uma função simplesmente atribuindo valores a vários parâmetros de saída.
Os artigos de referência de vinculação (filas de armazenamento, por exemplo) explicam quais tipos de parâmetros você pode usar com atributos de vinculação de gatilho, entrada ou saída.
Exemplo de expressões de vinculação
O código a seguir obtém o nome da fila a ser monitorada de uma configuração de aplicativo e obtém o tempo de criação da mensagem da fila insertionTime
no parâmetro.
public static class BindingExpressionsExample
{
[FunctionName("LogQueueMessage")]
public static void Run(
[QueueTrigger("%queueappsetting%")] string myQueueItem,
DateTimeOffset insertionTime,
ILogger log)
{
log.LogInformation($"Message content: {myQueueItem}");
log.LogInformation($"Created at: {insertionTime}");
}
}
function.json gerados automaticamente
O processo de compilação cria um arquivo de function.json em uma pasta de função na pasta de compilação. Como observado anteriormente, esse arquivo não deve ser editado diretamente. Não é possível alterar a configuração de vinculação ou desativar a função editando este arquivo.
O objetivo deste arquivo é fornecer informações ao controlador de escala para usar para decisões de dimensionamento no plano de consumo. Por esse motivo, o arquivo só tem informações de gatilho, não ligações de entrada/saída.
O arquivo de function.json gerado inclui uma configurationSource
propriedade que informa ao tempo de execução para usar atributos .NET para associações, em vez de function.json configuração. Eis um exemplo:
{
"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.Funções
A geração de arquivos function.json é realizada pelo pacote NuGet Microsoft.NET.Sdk.Functions.
O exemplo a seguir mostra as partes relevantes dos .csproj
arquivos que têm diferentes estruturas de destino do mesmo Sdk
pacote:
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.5.0" />
</ItemGroup>
Importante
A partir da versão 4.0.6517 das Ferramentas Principais, os projetos de modelo em processo devem fazer referência à versão 4.5.0 ou posterior do Microsoft.NET.Sdk.Functions
. Se uma versão anterior for usada, o func start
comando irá erro.
Entre as dependências do Sdk
pacote estão gatilhos e associações. Um projeto 1.x refere-se a gatilhos e associações 1.x porque esses gatilhos e ligações visam o .NET Framework, enquanto os gatilhos e ligações 4.x visam o .NET Core.
O Sdk
pacote também depende de Newtonsoft.Json, e indiretamente em WindowsAzure.Storage. Essas dependências garantem que seu projeto use as versões desses pacotes que funcionam com a versão de tempo de execução do Functions que o projeto destina. Por exemplo, Newtonsoft.Json
tem a versão 11 para o .NET Framework 4.6.1, mas o tempo de execução do Functions destinado ao .NET Framework 4.6.1 só é compatível com Newtonsoft.Json
o 9.0.1. Portanto, seu código de função nesse projeto também tem que usar Newtonsoft.Json
9.0.1.
O código-fonte para Microsoft.NET.Sdk.Functions
está disponível no repositório do GitHub azure-functions-vs-build-sdk.
Versão do tempo de execução local
O Visual Studio usa as Ferramentas Principais do Azure Functions para executar projetos do Functions em seu computador local. As Ferramentas Principais são uma interface de linha de comando para o tempo de execução do Functions.
Se você instalar as Ferramentas Principais usando o pacote do instalador do Windows (MSI) ou usando npm, isso não afetará a versão das Ferramentas Principais usada pelo Visual Studio. Para o tempo de execução do Functions versão 1.x, o Visual Studio armazena versões das Ferramentas Principais em %USERPROFILE%\AppData\Local\Azure.Functions.Cli e usa a versão mais recente armazenada lá. Para o Functions 4.x, as Ferramentas Principais estão incluídas na extensão Azure Functions and Web Jobs Tools . Para o Functions 1.x, você pode ver qual versão está sendo usada na saída do console quando você executa um projeto do 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
Você pode compilar seu aplicativo de função como binários ReadyToRun. O ReadyToRun é uma forma de compilação antecipada que pode melhorar o desempenho da inicialização para ajudar a reduzir o impacto do arranque a frio quando executado em um plano de consumo.
O ReadyToRun está disponível no .NET 6 e versões posteriores e requer a versão 4.0 do tempo de execução do Azure Functions.
Para compilar seu projeto como ReadyToRun, atualize seu arquivo de projeto adicionando os <PublishReadyToRun>
elementos e <RuntimeIdentifier>
. A seguir está a configuração para publicação em um aplicativo de função de 32 bits do Windows.
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<PublishReadyToRun>true</PublishReadyToRun>
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
</PropertyGroup>
Importante
A partir do .NET 6, foi adicionado suporte para a compilação Composite ReadyToRun. Confira as restrições de arquitetura e plataforma cruzada do ReadyToRun.
Você também pode criar seu aplicativo com ReadyToRun a partir da linha de comando. Para obter mais informações, consulte a -p:PublishReadyToRun=true
opção em dotnet publish
.
Tipos suportados para ligações
Cada ligação tem seus próprios tipos suportados; por exemplo, um atributo de gatilho de blob pode ser aplicado a um parâmetro string, um parâmetro POCO, um CloudBlockBlob
parâmetro ou qualquer um dos vários outros tipos suportados. O artigo de referência de vinculação para associações de blob lista todos os tipos de parâmetros suportados. Para obter mais informações, consulte Gatilhos e ligações e os documentos de referência de vinculação para cada tipo de associação.
Gorjeta
Se você planeja usar as ligações HTTP ou WebHook, planeje evitar o esgotamento da porta que pode ser causado pela instanciação incorreta do HttpClient
. Para obter mais informações, consulte Como gerenciar conexões no Azure Functions.
Vinculação ao valor de retorno do método
Você pode usar um valor de retorno de método para uma associação de saída, aplicando o atributo ao valor de retorno do método. Para obter exemplos, consulte Gatilhos e associações.
Use o valor de retorno somente se uma execução de função bem-sucedida sempre resultar em um valor de retorno para passar para a associação de saída. Caso contrário, use ICollector
ou IAsyncCollector
, conforme mostrado na seção a seguir.
Gravando vários valores de saída
Para gravar vários valores em uma ligação de saída, ou se uma invocação de função bem-sucedida pode não resultar em nada para passar para a associação de saída, use os ICollector
tipos ou IAsyncCollector
. Esses tipos são coleções somente gravação que são gravadas na associação de saída quando o método é concluído.
Este exemplo grava várias mensagens de fila na mesma fila usando ICollector
:
public static class ICollectorExample
{
[FunctionName("CopyQueueMessageICollector")]
public static void Run(
[QueueTrigger("myqueue-items-source-3")] string myQueueItem,
[Queue("myqueue-items-destination")] ICollector<string> myDestinationQueue,
ILogger log)
{
log.LogInformation($"C# function processed: {myQueueItem}");
myDestinationQueue.Add($"Copy 1: {myQueueItem}");
myDestinationQueue.Add($"Copy 2: {myQueueItem}");
}
}
Assíncrono
Para tornar uma função assíncrona, use a async
palavra-chave e retorne um Task
objeto.
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);
}
}
Não é possível usar out
parâmetros em funções assíncronas. Para ligações de saída, use o valor de retorno da função ou um objeto coletor.
Tokens de cancelamento
Uma função pode aceitar um parâmetro CancellationToken , que permite que o sistema operacional notifique seu código quando a função estiver prestes a ser encerrada. Você pode usar essa notificação para garantir que a função não seja encerrada inesperadamente de uma forma que deixe os dados em um estado inconsistente.
Considere o caso quando você tem uma função que processa mensagens em lotes. A seguinte função acionada pelo Barramento de Serviço do Azure processa uma matriz de objetos ServiceBusReceivedMessage, que representa um lote de mensagens de entrada a serem processadas por uma chamada de função específica:
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}");
}
}
}
}
Registo
No código da função, você pode gravar a saída em logs que aparecem como rastreamentos no Application Insights. A maneira recomendada de gravar nos logs é incluir um parâmetro do tipo ILogger, que normalmente é chamado log
de . Versão 1.x do tempo de execução do Functions usado TraceWriter
, que também grava no Application Insights, mas não oferece suporte ao log estruturado. Não use Console.Write
para gravar seus logs, pois esses dados não são capturados pelo Application Insights.
ILogger
Em sua definição de função, inclua um parâmetro ILogger , que suporta log estruturado.
Com um ILogger
objeto, você chama Log<level>
métodos de extensão no ILogger para criar logs. O código a seguir grava Information
logs com categoria Function.<YOUR_FUNCTION_NAME>.User.
:
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, ILogger logger)
{
logger.LogInformation("Request for item with key={itemKey}.", id);
Para saber mais sobre como o Functions implementa , consulte Coletando dados de ILogger
telemetria. Categorias prefixadas com Function
suposição de que você está usando uma ILogger
instância. Se, em vez disso, optar por utilizar um ILogger<T>
, o nome da categoria poderá basear-se em T
.
Registos estruturados
A ordem dos espaços reservados, não seus nomes, determina quais parâmetros são usados na mensagem de log. Suponha que você tenha o seguinte código:
string partitionKey = "partitionKey";
string rowKey = "rowKey";
logger.LogInformation("partitionKey={partitionKey}, rowKey={rowKey}", partitionKey, rowKey);
Se você mantiver a mesma cadeia de caracteres de mensagem e inverter a ordem dos parâmetros, o texto da mensagem resultante terá os valores nos lugares errados.
Os espaços reservados são tratados dessa maneira para que você possa fazer o log estruturado. O Application Insights armazena os pares nome-valor do parâmetro e a cadeia de caracteres da mensagem. O resultado é que os argumentos da mensagem se tornam campos nos quais você pode consultar.
Se a chamada do método do registrador se parecer com o exemplo anterior, você poderá consultar o campo customDimensions.prop__rowKey
. O prop__
prefixo é adicionado para garantir que não haja colisões entre campos que o tempo de execução adiciona e campos que seu código de função adiciona.
Você também pode consultar a cadeia de caracteres da mensagem original fazendo referência ao campo customDimensions.prop__{OriginalFormat}
.
Aqui está um exemplo de representação JSON de customDimensions
dados:
{
"customDimensions": {
"prop__{OriginalFormat}":"C# Queue trigger function processed: {message}",
"Category":"Function",
"LogLevel":"Information",
"prop__message":"c9519cbf-b1e6-4b9b-bf24-cb7d10b1bb89"
}
}
Telemetria personalizada de log
Há uma versão específica do SDK do Application Insights que você pode usar para enviar dados de telemetria personalizados de suas funções para o Application Insights: Microsoft.Azure.WebJobs.Logging.ApplicationInsights. Use o seguinte comando no prompt de comando para instalar este pacote:
dotnet add package Microsoft.Azure.WebJobs.Logging.ApplicationInsights --version <VERSION>
Neste comando, substitua <VERSION>
por uma versão deste pacote que ofereça suporte à versão instalada do Microsoft.Azure.WebJobs.
Os exemplos de C# a seguir usam a API de telemetria personalizada. O exemplo é para uma biblioteca de classes .NET, mas o código do Application Insights é o mesmo para o script C#.
A versão 2.x e versões posteriores do tempo de execução usam recursos mais recentes no Application Insights para correlacionar automaticamente a telemetria com a operação atual. Não há necessidade de definir manualmente a operação Id
, ParentId
ou Name
campos.
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());
}
}
}
Neste exemplo, os dados de métricas personalizadas são agregados pelo host antes de serem enviados para a tabela customMetrics. Para saber mais, consulte a documentação do GetMetric em Application Insights.
Ao executar localmente, você deve adicionar a APPINSIGHTS_INSTRUMENTATIONKEY
configuração, com a chave do Application Insights, ao arquivo local.settings.json .
Não ligue TrackRequest
ou StartOperation<RequestTelemetry>
porque você verá solicitações duplicadas para uma chamada de função. O tempo de execução do Functions rastreia automaticamente as solicitações.
Não defina telemetryClient.Context.Operation.Id
. Essa configuração global causa correlação incorreta quando muitas funções estão sendo executadas simultaneamente. Em vez disso, crie uma nova instância de telemetria (DependencyTelemetry
, EventTelemetry
) e modifique sua Context
propriedade. Em seguida, passe a instância de telemetria para o método correspondente Track
em TelemetryClient
(TrackDependency()
, TrackEvent()
TrackMetric()
, ). Esse método garante que a telemetria tenha os detalhes de correlação corretos para a chamada de função atual.
Testar funções
Os artigos a seguir mostram como executar uma função de biblioteca de classes C# em processo localmente para fins de teste:
Variáveis de ambiente
Para obter uma variável de ambiente ou um valor de configuração de aplicativo, use System.Environment.GetEnvironmentVariable
, conforme mostrado no exemplo de código a seguir:
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);
}
}
As configurações do aplicativo podem ser lidas a partir de variáveis de ambiente ao desenvolver localmente e ao executar no Azure. Ao desenvolver localmente, as configurações do aplicativo vêm da Values
coleção no arquivo local.settings.json. Em ambos os ambientes, local e Azure, GetEnvironmentVariable("<app setting name>")
recupera o valor da configuração do aplicativo nomeado. Por exemplo, quando você estiver executando localmente, "Nome do Meu Site" será retornado se o arquivo local.settings.json contiver { "Values": { "WEBSITE_SITE_NAME": "My Site Name" } }
arquivos .
A propriedade System.Configuration.ConfigurationManager.AppSettings é uma API alternativa para obter valores de configuração de aplicativo, mas recomendamos que você use GetEnvironmentVariable
conforme mostrado aqui.
Vinculação em tempo de execução
Em C# e outras linguagens .NET, você pode usar um padrão de vinculação imperativa , em oposição às associações declarativas em atributos. A vinculação imperativa é útil quando os parâmetros de vinculação precisam ser calculados em tempo de execução em vez de tempo de design. Com esse padrão, você pode vincular ligações de entrada e saída suportadas on-the-fly em seu código de função.
Defina uma ligação imperativa da seguinte forma:
Não inclua um atributo na assinatura da função para as ligações imperativas desejadas.
Passe um parâmetro
Binder binder
de entrada ouIBinder binder
.Use o seguinte padrão C# para executar a associação de dados.
using (var output = await binder.BindAsync<T>(new BindingTypeAttribute(...))) { ... }
BindingTypeAttribute
é o atributo .NET que define sua associação eT
é um tipo de entrada ou saída suportado por esse tipo de associação.T
não pode ser um tipo deout
parâmetro (comoout JObject
). Por exemplo, a vinculação de saída da tabela Aplicativos Móveis suporta seis tipos de saída, mas você só pode usar ICollector<T> ou IAsyncCollector<T> com vinculação imperativa.
Exemplo de atributo único
O código de exemplo a seguir cria uma ligação de saída de blob de armazenamento com caminho de blob definido em tempo de execução e, em seguida, grava uma cadeia de caracteres no blob.
public static class IBinderExample
{
[FunctionName("CreateBlobUsingBinder")]
public static void Run(
[QueueTrigger("myqueue-items-source-4")] string myQueueItem,
IBinder binder,
ILogger log)
{
log.LogInformation($"CreateBlobUsingBinder function processed: {myQueueItem}");
using (var writer = binder.Bind<TextWriter>(new BlobAttribute(
$"samples-output/{myQueueItem}", FileAccess.Write)))
{
writer.Write("Hello World!");
};
}
}
BlobAttribute define a ligação de entrada ou saída do blob de armazenamento e TextWriter é um tipo de ligação de saída suportado.
Exemplo de vários atributos
O exemplo anterior obtém a configuração do aplicativo para a cadeia de conexão principal da conta de armazenamento do aplicativo de função (que é AzureWebJobsStorage
). Você pode especificar uma configuração de aplicativo personalizada a ser usada para a conta de armazenamento adicionando o StorageAccountAttribute e passando a matriz de atributos para BindAsync<T>()
. Use um Binder
parâmetro, não IBinder
. Por exemplo:
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!!");
}
}
}
Acionadores e enlaces
Esta tabela mostra as associações com suporte nas versões principais do tempo de execução do Azure Functions:
Type | 1,x1 | 2.x e superior2 | Acionador | Entrada | Saída |
---|---|---|---|---|---|
Armazenamento de blobs | ✔ | ✔ | ✔ | ✔ | ✔ |
BD do Cosmos para o Azure | ✔ | ✔ | ✔ | ✔ | ✔ |
Azure Data Explorer | ✔ | ✔ | ✔ | ||
SQL do Azure | ✔ | ✔ | ✔ | ✔ | |
Dapr4 | ✔ | ✔ | ✔ | ✔ | |
Event Grid | ✔ | ✔ | ✔ | ✔ | |
Hubs de Eventos | ✔ | ✔ | ✔ | ✔ | |
HTTP & webhooks | ✔ | ✔ | ✔ | ✔ | |
Hub IoT | ✔ | ✔ | ✔ | ||
Kafka3 | ✔ | ✔ | ✔ | ||
Aplicações Móveis | ✔ | ✔ | ✔ | ||
Hubs de Notificação | ✔ | ✔ | |||
Armazenamento de filas | ✔ | ✔ | ✔ | ✔ | |
Redis | ✔ | ✔ | |||
CoelhoMQ3 | ✔ | ✔ | ✔ | ||
SendGrid | ✔ | ✔ | ✔ | ||
Service Bus | ✔ | ✔ | ✔ | ✔ | |
SignalR | ✔ | ✔ | ✔ | ✔ | |
Armazenamento de tabelas | ✔ | ✔ | ✔ | ✔ | |
Temporizador | ✔ | ✔ | ✔ | ||
Twilio | ✔ | ✔ | ✔ |
Notas:
- O suporte terminará para a versão 1.x do tempo de execução do Azure Functions em 14 de setembro de 2026. É altamente recomendável que você migre seus aplicativos para a versão 4.x para obter suporte completo.
- A partir do tempo de execução da versão 2.x, todas as associações, exceto HTTP e Timer, devem ser registradas. Consulte Registrar extensões de vinculação.
- Os gatilhos não são suportados no plano de consumo. Requer gatilhos controlados por tempo de execução.
- Suportado apenas em Kubernetes, IoT Edge e outros modos auto-hospedados.