Поделиться через


Разработка функций библиотеки классов C# с помощью службы "Функции Azure"

Эта статья описывает разработку функций Azure с помощью C# в библиотеках классов .NET. Эти библиотеки классов используются для выполнения в процессе с средой выполнения Функций. Функции .NET также могут выполнять _isolated из среды выполнения функций, что дает несколько преимуществ. Дополнительные сведения см . в изолированной рабочей модели. Полное сравнение этих двух моделей см. в разделе "Различия между внутрипроцессной моделью и изолированной рабочей моделью".

Внимание

В этой статье описываются функции библиотеки классов .NET, которые выполняются внутри процесса в среде выполнения. Функции C# также могут выполняться во внепроцессном режиме и изолированы от среды выполнения функций. Модель изолированного рабочего процесса — единственный способ запуска версий .NET и платформа .NET Framework приложений в текущих версиях среды выполнения Функций. Дополнительные сведения см. в статье об изолированных рабочих функциях .NET. Полное сравнение между изолированным рабочим процессом и функциями .NET в процессе см. в разделе "Различия между внутрипроцессным процессом и изоляцией рабочего процесса .NET Функции Azure".

Разработчику C# также могут быть полезны следующие статьи.

Начало работы Основные понятия Интерактивное обучение и примеры

Решение "Функции Azure" поддерживает языки программирования C# и скрипт C#. Рекомендации по использованию C# на портале Azure см. в справочнике разработчика скриптов C# (.csx).

Поддерживаемые версии

Версии среды выполнения функций поддерживают определенные версии .NET. Дополнительные сведения о версиях службы "Функции Azure" см. в разделе Обзор версий среды выполнения службы "Функции Azure". Поддержка версий также зависит от того, выполняются ли функции в процессе или изолированном рабочем процессе.

Примечание.

Чтобы узнать, как изменить версию среды выполнения Функций, используемую приложением-функцией, обратитесь к разделу Просмотр и обновление текущей версии среды выполнения.

В следующей таблице показан самый высокий уровень .NET или платформа .NET Framework, который можно использовать с определенной версией Функций.

Версия среды выполнения службы "Функции Azure" Изолированная рабочая модель Модель в процессе5
Функции версии 4.x1 .NET 9.0 (предварительная версия)
.NET 8.0
.NET 6.02
платформа .NET Framework 4.83
.NET 8.0
.NET 6.02
Функции 1.x4 Н/Д .NET Framework 4.8

1 .NET 7 ранее поддерживается в изолированной рабочей модели, но достигла конца официальной поддержки 14 мая 2024 года.

2 .NET 6 достигает окончания официальной поддержки 12 ноября 2024 года.

3 Процесс сборки также требует пакета SDK для .NET.

4 Поддержка заканчивается для версии 1.x среды выполнения Функции Azure 14 сентября 2026 года. Дополнительные сведения см . в этом объявлении о поддержке. Для дальнейшей полной поддержки следует перенести приложения в версию 4.x.

5 Поддержка заканчивается для модели в процессе 10 ноября 2026 года. Дополнительные сведения см . в этом объявлении о поддержке. Для непрерывной поддержки следует перенести приложения в изолированную рабочую модель.

Последние новости о выпусках службы "Функции Azure", включая удаление отдельных устаревших промежуточных версий, см. в статье Анонсы для службы приложений Azure.

Обновление до целевого .NET 8

Приложения, использующие модель в процессе, могут нацелиться на .NET 8, выполнив действия, описанные в этом разделе. Тем не менее, если вы решили выполнить этот параметр, необходимо начать планирование миграции на изолированную рабочую модель заранее, чтобы завершить поддержку модели в процессе 10 ноября 2026 года.

Многие приложения могут изменять конфигурацию приложения-функции в Azure без обновлений кода или повторного развертывания. Чтобы запустить .NET 8 с моделью в процессе, требуются три конфигурации:

  • Параметр FUNCTIONS_WORKER_RUNTIME приложения должен быть задан со значением dotnet.
  • Параметр FUNCTIONS_EXTENSION_VERSION приложения должен быть задан со значением ~4.
  • Параметр FUNCTIONS_INPROC_NET8_ENABLED приложения должен быть задан со значением "1".
  • Чтобы ссылаться на .NET 8, необходимо обновить конфигурацию стека.

Поддержка .NET 8 по-прежнему использует версию 4.x среды выполнения Функций и не требует изменений в настроенной версии среды выполнения.

Чтобы обновить локальный проект, сначала убедитесь, что вы используете последние версии локальных средств. Затем убедитесь, что проект ссылается на версии 4.4.0 или более поздней версии Microsoft.NET.Sdk.Functions. Затем вы можете изменить значение TargetFramework "net8.0". Необходимо также обновить, local.settings.json чтобы включить как значение dotnet, так FUNCTIONS_WORKER_RUNTIME и FUNCTIONS_INPROC_NET8_ENABLED задать значение "1".

Ниже приведен пример минимального project файла с этими изменениями:

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

Ниже приведен пример минимального local.settings.json файла с этими изменениями:

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

Если приложение используется Microsoft.Azure.DurableTask.Netherite.AzureFunctions, убедитесь, что он предназначен для версии 1.5.3 или более поздней. Из-за изменения поведения в .NET 8 приложения с более старыми версиями пакета вызовет неоднозначное исключение конструктора.

Возможно, вам потребуется внести другие изменения в приложение на основе поддержки версий других зависимостей.

Версия 4.x среды выполнения Функций предоставляет эквивалентные функциональные возможности для .NET 6 и .NET 8. Модель в процессе не включает дополнительные функции или обновления, которые интегрируются с новыми возможностями .NET 8. Например, среда выполнения не поддерживает ключи служб. Чтобы воспользоваться всеми преимуществами последних возможностей и улучшений .NET 8, необходимо перейти на изолированную рабочую модель.

Проект библиотеки классов функций

В Visual Studio шаблон проекта Функции Azure создает проект библиотеки классов C#, содержащий следующие файлы:

  • host.json — хранит параметры конфигурации, которые влияют на все функции в проекте при выполнении в локальной среде или в Azure.
  • local.settings.json — хранит параметры приложений и строки подключения, которые используются при выполнении в локальной среде. Этот файл содержит секретные данные и не будет опубликован в приложении-функции в Azure. Вместо этого необходимо добавить параметры приложения для приложения-функции.

При построении проекта в выходном каталоге создается приблизительно такая структура папок:

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

Этот каталог — то, что будет развернуто в вашем приложении-функции в Azure. Расширения привязки, необходимые в версии 2.x среды выполнения функций, добавляются в проект как пакеты NuGet.

Внимание

Процесс сборки создает файл function.json для каждой функции. Этот файл function.json не предназначен для непосредственного редактирования. Невозможно изменить конфигурацию привязки или отключить функцию путем редактирования этого файла. Чтобы узнать, как отключить функцию, см. раздел Отключение функций.

Методы, распознаваемые как функции

В библиотеке классов функция — это метод с FunctionName атрибутом триггера, как показано в следующем примере:

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

Атрибут FunctionName помечает метод как точку входа функции. Имя в проекте должно быть уникальным, начинаться с буквы и содержать только буквы, цифры, _ и -, а его длина не должна превышать 127 знаков. Шаблоны проектов часто создают метод Run, но метод может иметь любое допустимое имя для метода C#. В приведенном выше примере показан используемый статический метод, но функции не требуются для статического.

Атрибут триггера указывает тип триггера и привязывает входные данные к параметру метода. Пример функции срабатывает по сообщению очереди, а сообщение очереди передается методу в параметре myQueueItem.

Параметры сигнатуры метода

Сигнатура метода может содержать параметры, отличные от используемых с атрибутом триггера. Ниже приведен ряд других параметров, которые можно включить:

Порядок параметров в сигнатуре функции не имеет значения. Например, можно указать параметры триггера до или после других привязок, а параметр для средства ведения журнала — до или после параметров триггера или привязки.

Выходные привязки

Функция может иметь ноль или несколько выходных привязок, определенных с помощью выходных параметров.

В следующем примере изменяется предыдущий путем добавления привязки очереди вывода с именем myQueueItemCopy. Функция записывает содержимое сообщения, которое запускает функцию для нового сообщения в другой очереди.

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

Значения, назначенные выходным привязкам, записываются при выходе из функции. В функции можно использовать несколько выходных привязок, просто назначив значения нескольким выходным параметрам.

В справочных статьях по привязкам (например, Привязки хранилища очередей Azure для службы "Функции Azure") объясняется, какие типы параметров можно использовать с триггерами, а также с атрибутами входных или выходных привязок.

Пример выражений привязки

Приведенный ниже код позволяет получить имя очереди для мониторинга из настроек приложения и время создания сообщения очереди в параметре 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}");
    }
}

Автоматически созданный файл function.json

Процесс сборки создает файл function.json в папке функции в папке сборки. Как отмечалось ранее, этот файл не предназначен для непосредственного редактирования. Невозможно изменить конфигурацию привязки или отключить функцию путем редактирования этого файла.

Назначение этого файла — предоставить сведения контроллеру масштаба для принятия решений о масштабировании плана потребления. По этой причине файл содержит только сведения о триггерах, но не о входных или выходных привязках.

Создаваемый файл function.json содержит свойство configurationSource, которое указывает среде выполнения использовать атрибуты .NET для привязок, вместо конфигурации function.json. Приведем пример:

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

Создание файла function.json выполняется пакетом NuGet Microsoft.NET.Sdk.Functions.

В следующем примере показаны соответствующие части .csproj файлов с разными целевыми платформами Sdk одного пакета:

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

Внимание

Начиная с версии 4.0.6517 основных инструментов проекты модели в процессе должны ссылаться на версию 4.5.0 или более поздней версии Microsoft.NET.Sdk.Functions. Если используется более ранняя версия, func start команда будет ошибкой.

К зависимостям пакетов Sdk относятся триггеры и привязки. Проект 1.x ссылается на триггеры и привязки версии 1.x, так как эти триггеры и привязки предназначены для платформа .NET Framework, а триггеры и привязки 4.x предназначены для .NET Core.

Пакет Sdk также зависит от пакета Newtonsoft.Json и косвенно от пакета WindowsAzure.Storage. Эти зависимости гарантируют, что проект использует версии пакетов, совместимые с версией среды выполнения Функций, для которой он предназначен. Например, при использовании платформы .NET Framework 4.6.1 пакет Newtonsoft.Json имеет версию 11, но среда выполнения Функций, предназначенная для платформы .NET Framework 4.6.1, совместима только с пакетом Newtonsoft.Json версии 9.0.1. Поэтому код функции в этом проекте также должен использовать пакет Newtonsoft.Json версии 9.0.1.

Исходный код пакета Microsoft.NET.Sdk.Functions доступен в репозитории GitHub azure-functions-vs-build-sdk.

Версия локальной среды выполнения

Visual Studio выполняет проекты Функций на локальном компьютере с помощью Azure Functions Core Tools. Основные инструменты — это интерфейс командной строки среды выполнения Функций.

Если установить основные инструменты с помощью пакета установщика Windows (MSI) или с помощью npm, это не влияет на версию Основных инструментов, используемую Visual Studio. Версии основных инструментов среды выполнения Функций 1.x хранятся в файле %USERPROFILE%\AppData\Local\Azure.Functions.Cli. Visual Studio использует последнюю версию. Для функций 4.x основные инструменты включены в расширение Функции Azure и средств веб-заданий. В функциях 1.x вы увидите, какая версия используется в выходных данных консоли при запуске проекта Функций:

[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

Приложение-функцию можно скомпилировать как двоичные файлы ReadytoRun. ReadyToRun представляет собой форму предварительной компиляции, которая позволяет повысить производительность при запуске, чтобы снизить влияние холодного запуска при запуске в План потребления.

ReadyToRun доступен в .NET 6 и более поздних версиях и требует версии 4.0 среды выполнения Функции Azure.

Чтобы скомпилировать проект как ReadyToRun, обновите файл проекта, добавив элементы <PublishReadyToRun> и <RuntimeIdentifier>. Ниже приведена конфигурация для публикации в 32-разрядном приложении-функции Windows.

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

Внимание

Начиная с .NET 6 добавлена поддержка составной компиляции ReadyToRun. Ознакомьтесь с ограничениями платформы и архитектуры ReadyToRun Cross.

Кроме того, можно создать приложение с помощью ReadyToRun из командной строки. Дополнительные сведения см. в подразделе о параметре -p:PublishReadyToRun=true, раздел dotnet publish.

Поддерживаемые типы для привязок

Все привязки поддерживают определенные типы. Например, атрибут триггера большого двоичного объекта можно применить к строковому параметру, параметру POCO, параметру CloudBlockBlob или любому из нескольких других поддерживаемых типов. В справочной статье о привязках для больших двоичных объектов содержится список всех поддерживаемых типов параметров. Дополнительные сведения см. в статье о триггерах и привязках и в справочной документации по каждому типу привязки.

Совет

Если вы планируете использовать привязки HTTP или веб-перехватчика, спланируйте работу так, чтобы избежать нехватки портов, которая может возникнуть в результате неправильной установки HttpClient. См. дополнительные сведения об управлении подключениями в службе "Функции Azure".

Привязка к возвращаемому значению метода

Возвращаемое значение метода можно использовать для привязки выходных данных. Для этого примените атрибут к возвращаемому значению метода. Примеры см. в статье о триггерах и привязках.

Используйте возвращаемое значение, только если в результате успешного выполнения функции всегда возвращается значение для передачи в привязку для вывода. В противном случае используйте ICollector или IAsyncCollector, как указано в следующем разделе.

Написание нескольких значений выходных данных

Чтобы записать несколько значений в привязку для вывода или если после успешного вызова функции не возвращается значение для передачи в привязку для вывода, используйте типы ICollector или IAsyncCollector. Эти типы представляют собой доступные только для записи коллекции, записываемые в выходную привязку по завершении метода.

В следующем примере записываются несколько сообщений очереди в ту же очередь с помощью 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 и верните объект Task.

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

Вы не можете использовать параметры out в асинхронных функциях. Вместо этих параметров для выходных привязок используйте возвращаемое значение функции или объект сборщика.

Токены отмены

Функция может принимать параметр CancellationToken, который позволяет операционной системе передавать в ваш код сведения о том, что выполнение функции будет завершено. Это уведомление можно использовать для предотвращения ситуации, когда выполнение функции завершается неожиданно, оставляя данные в несогласованном состоянии.

Рассмотрим ситуацию, когда у вас есть функция, которая обрабатывает сообщения пакетами. Следующая функция Служебная шина Azure обрабатывает массив объектов ServiceBusReceivedMessage, который представляет пакет входящих сообщений для обработки определенным вызовом функции:

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

Ведение журнала

В коде функции вы можете записывать выходные данные в журналы, которые отображаются в виде трассировок в Application Insights. Рекомендуемый способ записи в журналы — включить параметр типа ILogger, который обычно называется log. Версия 1.x среды выполнения службы "Функции Azure" использует TraceWriter, который также выполняет запись в Application Insights, но не поддерживает структурированное ведение журнала. Не следует использовать Console.Write для записи журналов, так как эти данные не фиксируются Application Insights.

ILogger

Включите в определение функции параметр ILogger, который поддерживает структурированное ведение журнала.

Объект ILogger позволяет вызывать для создания журналов методы расширения ILoggerLog<level>. Следующий код записывает журнал Information с категорией Function.<YOUR_FUNCTION_NAME>.User..

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

Дополнительные сведения о реализации ILogger в службе "Функции Azure" см. в разделе Сбор данных телеметрии. Категории, префиксированные с Function предположением, что вы используете ILogger экземпляр. Если вместо этого вы решили использовать ILogger<T>, имя категории может основываться на T.

Структурированное ведение журнала

Использование параметров в сообщении журнала определяется порядком заполнителей, а не их именами. Предположим, что у вас есть следующий код:

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

Если вы примените эту же строку сообщения с обратным порядком параметров, в тексте сообщения значения окажутся на неправильных местах.

Такой метод обработки заполнителей позволяет выполнять структурированное ведение журналов. Application Insights сохраняет не только строку сообщения, но и параметры в формате пар "имя-значение". Благодаря этому все аргументы сообщения становятся полями, по которым можно выполнять запросы.

Если используется метод ведения журнала из предыдущего примера, вы сможете отправить запрос поля customDimensions.prop__rowKey. При этом добавляется префикс prop__, чтобы не возникало конфликтов между полями, которые добавляет среда выполнения и которые добавляет код вашей функции.

Исходную строку сообщения можно получить, указав в запросе поле customDimensions.prop__{OriginalFormat}.

Ниже приведен пример JSON-представления для данных customDimensions.

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

Ведение журнала пользовательской телеметрии

Существует определенная версия пакета SDK Application Insights, которую можно использовать для отправки пользовательских данных телеметрии из функций в Application Insights: Microsoft.Azure.WebJobs.Logging.ApplicationInsights. Для установки этого пакета используйте следующую команду из командной строки:

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

В этой команде замените <VERSION> версией этого пакета, которая поддерживает установленную версию Microsoft.Azure.WebJobs.

В следующем примере C# используется настраиваемый интерфейс API телеметрии. Пример приведен для библиотеки классов .NET, но код Application Insights в скрипте C# будет точно таким же.

Среда выполнения версии 2.x или более поздних использует новые функции в Application Insights для выполнения автоматической корреляции данных телеметрии с текущей операцией. Нет необходимости вручную задавать для операции поля Id, ParentId или Name.

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

В этом примере пользовательские данные метрики объединяются хостом перед отправкой в таблицу customMetrics. Дополнительные сведения см. в документации по в Application Insights.

В случае локального запуска необходимо добавить параметр APPINSIGHTS_INSTRUMENTATIONKEY с ключом Application Insights в файл local.settings.json.

Не вызывайте TrackRequest или StartOperation<RequestTelemetry>, ведь при этом будут отображаться повторные запросы на вызов функции. Среда выполнения Функций Azure автоматически отслеживает запросы.

Не указывайте telemetryClient.Context.Operation.Id. Этот глобальный параметр может вызвать неправильную корреляцию при одновременном выполнении нескольких функций. Вместо этого создайте экземпляр телеметрии (DependencyTelemetry, EventTelemetry) и измените его свойство Context. Затем передайте экземпляр телеметрии в соответствующий метод Track в TelemetryClient (TrackDependency(), TrackEvent(), TrackMetric()). Этот метод гарантирует правильность сведений о корреляции телеметрии для текущего вызова функции.

Функции тестирования

В следующих статьях показано, как локально запустить функцию библиотеки классов C# внутри процесса для тестирования:

Переменные среды

Чтобы получить значение переменной среды или значение параметра приложения, используйте System.Environment.GetEnvironmentVariable, как показано в следующем примере кода.

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

Параметры приложения могут считываться из переменных среды при разработке локально и при запуске в Azure. При локальной разработке параметры приложения поступают из коллекции Values файла local.settings.json. Значение именованного параметра приложения GetEnvironmentVariable("<app setting name>") извлекается в локальной среде и среде Azure. Например, при локальном запуске будет возвращено "Имя_сайта", если файл local.settings.json содержит { "Values": { "WEBSITE_SITE_NAME": "My Site Name" } }.

Свойство System.Configuration.ConfigurationManager.AppSettings — альтернативный API-интерфейс для получения значения параметра приложения, но рекомендуется использовать GetEnvironmentVariable, как показано ниже.

Привязка во время выполнения

Для C# и других языков .NET можно использовать шаблон императивной привязки, которая отличается от декларативной привязки в атрибутах. Императивную привязку удобно использовать, когда параметры привязки должны вычисляться не при проектировании, а во время выполнения. С использованием такого шаблона можно моментально выполнить привязку к поддерживаемым входным и выходным привязкам в коде функции.

Определите принудительную привязку следующим образом.

  • Не добавляйте атрибут в сигнатуру функции для нужных императивных привязок.

  • Передайте входной параметр Binder binder или IBinder binder.

  • Используйте следующий шаблон C# для привязки данных,

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

    где BindingTypeAttribute — атрибут .NET, определяющий пользовательскую привязку, а T — входной или выходной тип, поддерживаемый этим типом привязки. T не может быть типом out параметра (например out JObject, ). Например, выходная привязка таблицы мобильных приложений поддерживает шесть выходных типов, но с императивной привязкой можно использовать только ICollector<T> или IAsyncCollector<T>.

Пример с одним атрибутом

В следующем примере кода создается выходная привязка большого двоичного объекта службы хранилища с путем к большому двоичному объекту, определенному во время выполнения, а затем записывается строка в большой двоичный объект.

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 определяет входную или выходную привязку большого двоичного объекта службы хранилища, а TextWriter представляет собой поддерживаемый тип выходной привязки.

Пример с несколькими атрибутами

В предыдущем примере код получает параметр приложения для строки подключения основной учетной записи хранения приложения-функции (т. е. AzureWebJobsStorage). Вы можете указать пользовательский параметр приложения, который следует использовать для учетной записи хранения. Для этого добавьте StorageAccountAttribute и передайте массив атрибутов в BindAsync<T>(). Используйте параметр Binder, а не IBinder. Например:

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

Триггеры и привязки

В этой таблице показаны привязки, которые поддерживаются в двух основных версиях среды выполнения Функций Azure.

Тип 1.x1 2.x и выше2 Триггер Входные данные Выходные данные
Хранилище BLOB-объектов
Azure Cosmos DB
Обозреватель данных Azure
Azure SQL
Dapr4
Сетка событий
Центры событий
HTTP и веб-перехватчики
Центр IoT
Kafka3
Мобильные приложения
Центры уведомлений
Хранилище очередей
Redis
RabbitMQ3
SendGrid
Служебная шина
SignalR
Хранилище таблиц
Таймер
Twilio

Примечания:

  1. Поддержка будет завершена для среды выполнения Функции Azure версии 1.x 14 сентября 2026 г. Настоятельно рекомендуется перенести приложения в версию 4.x для полной поддержки.
  2. Начиная с среды выполнения версии 2.x все привязки, кроме ПРОТОКОЛА HTTP и Таймера, должны быть зарегистрированы. Ознакомьтесь с разделом Регистрация расширений привязки.
  3. Триггеры не поддерживаются в плане потребления. Требуются триггеры, управляемые средой выполнения.
  4. Поддерживается только в Kubernetes, IoT Edge и других автономных режимах.

Следующие шаги