Azure Functions C# 脚本 (.csx) 开发人员参考

本文介绍了如何使用 C# 脚本 ( .csx) 开发 Azure Functions。

重要

支持 C# 脚本主要是为了提供方便的门户内体验,以帮助你快速开始创建和运行 C# 函数。 对于生产质量的应用,应改为在本地开发 C# 函数,作为已编译的 C# 类库项目。 要了解如何将 C# 脚本项目迁移到 C# 类库(独立辅助角色)项目,请参阅将 C# 脚本应用转换为 C# 项目

借助 Azure Functions,可通过以下方式之一使用 C# 开发函数:

类型 执行进程 代码扩展 开发环境 参考
C# 脚本 进程内 .csx Portal
Core Tools
本文
C# 类库(隔离辅助角色) 独立工作进程 .cs Visual Studio
Visual Studio Code
Core Tools
.NET 独立工作进程函数
C# 类库(进程内) 进程内 .cs Visual Studio
Visual Studio Code
Core Tools
进程内 C# 类库函数

.csx 的工作原理

数据通过方法参数流入 C # 函数。 参数名称在 function.json 文件中指定,而预定义的名称则用于访问函数记录器和取消令牌等内容。

.csx 格式允许编写更少的“样本”,因此你可以集中编写 C# 函数。 只需定义 Run 方法即可,无需将所有内容都包装在命名空间和类中。 像往常一样,在文件开头包含任何程序集引用和命名空间。

初始化实例时,会编译函数应用的 .csx 文件。 此编译步骤意味着,与 C# 类库相比,冷启动之类的操作对于 C# 脚本函数来说可能需要更长的时间。 此编译步骤也说明了为何 C# 脚本函数在 Azure 门户中可以编辑,而 C# 类库则不可以编辑。

文件夹结构

C# 脚本项目的文件夹结构如下例所示:

FunctionsProject
 | - MyFirstFunction
 | | - run.csx
 | | - function.json
 | | - function.proj
 | - MySecondFunction
 | | - run.csx
 | | - function.json
 | | - function.proj
 | - host.json
 | - extensions.csproj
 | - bin

存在共享的 host.json 文件,可用于配置函数应用。 每个函数都具有自己的代码文件 (.csx) 和绑定配置文件 (function.json)。

2.x 版及更高版本的 Functions 运行时中所需的绑定扩展在 extensions.csproj 文件中定义,实际库文件位于 bin 文件夹中。 本地开发时,必须注册绑定扩展。 在 Azure 门户中开发函数时,系统将为你完成此注册。

绑定到参数

输入或输出数据通过 function.json 配置文件中的 name 属性绑定到 C# 脚本函数参数。 以下示例显示了一个 function.json 文件以及适用于队列触发函数的 run.csx 文件。 从队列消息接收数据的参数名为 myQueueItem,因为这是 name 属性的值。

{
    "disabled": false,
    "bindings": [
        {
            "type": "queueTrigger",
            "direction": "in",
            "name": "myQueueItem",
            "queueName": "myqueue-items",
            "connection":"MyStorageConnectionAppSetting"
        }
    ]
}
#r "Microsoft.WindowsAzure.Storage"

using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage.Queue;
using System;

public static void Run(CloudQueueMessage myQueueItem, ILogger log)
{
    log.LogInformation($"C# Queue trigger function processed: {myQueueItem.AsString}");
}

本文后面#r 语句做了解释。

绑定支持的类型

每个绑定都具有其自己支持的类型;例如,Blob 触发器可以与字符串参数、POCO 参数、CloudBlockBlob 参数或任何其他几种受支持类型之一配合使用。 适用于 Blob 绑定的绑定参考文章列出了适用于 Blob 触发器的所有受支持参数类型。 有关详细信息,请参阅触发器和绑定每个绑定类型的绑定参考文档

提示

如果计划使用 HTTP 或 WebHook 绑定,请制定计划来避免因实例化 HttpClient 不当导致的端口耗尽现象。 有关详细信息,请参阅如何在 Azure Functions 中管理连接

引用自定义类

如需使用自定义的普通旧 CLR 对象 (POCO) 类,可以将类定义包括在同一文件中,也可以将其置于单独的文件中。

以下示例显示了一个 run.csx 示例,后者包括一个 POCO 类定义。

public static void Run(string myBlob, out MyClass myQueueItem)
{
    log.Verbose($"C# Blob trigger function processed: {myBlob}");
    myQueueItem = new MyClass() { Id = "myid" };
}

public class MyClass
{
    public string Id { get; set; }
}

POCO 类必须为每个属性定义 getter 和 setter。

重用.csx 代码

可以在 run.csx 文件中使用其他 .csx 文件中定义的类和方法。 为此,需使用 run.csx 文件中的 #load 指令。 在下面的实例中,在 myLogger.csx 中共享了名为 MyLogger 的日志记录例程,并使用 #load 指令将其加载到 run.csx

示例 run.csx

#load "mylogger.csx"

using Microsoft.Extensions.Logging;

public static void Run(TimerInfo myTimer, ILogger log)
{
    log.LogInformation($"Log by run.csx: {DateTime.Now}");
    MyLogger(log, $"Log by MyLogger: {DateTime.Now}");
}

示例 mylogger.csx

public static void MyLogger(ILogger log, string logtext)
{
    log.LogInformation(logtext);
}

若要使用 POCO 对象强类型化在函数间传递的数据,常见模式是使用共享的 .csx 文件。 在下面的简化示例中,一个 HTTP 触发器和队列触发器共享名为 Order 的 POCO 对象以强类型化顺序数据:

HTTP 触发器的示例 run.csx

#load "..\shared\order.csx"

using System.Net;
using Microsoft.Extensions.Logging;

public static async Task<HttpResponseMessage> Run(Order req, IAsyncCollector<Order> outputQueueItem, ILogger log)
{
    log.LogInformation("C# HTTP trigger function received an order.");
    log.LogInformation(req.ToString());
    log.LogInformation("Submitting to processing queue.");

    if (req.orderId == null)
    {
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
    }
    else
    {
        await outputQueueItem.AddAsync(req);
        return new HttpResponseMessage(HttpStatusCode.OK);
    }
}

队列触发器的示例 run.csx

#load "..\shared\order.csx"

using System;
using Microsoft.Extensions.Logging;

public static void Run(Order myQueueItem, out Order outputQueueItem, ILogger log)
{
    log.LogInformation($"C# Queue trigger function processed order...");
    log.LogInformation(myQueueItem.ToString());

    outputQueueItem = myQueueItem;
}

示例 order.csx

public class Order
{
    public string orderId {get; set; }
    public string custName {get; set;}
    public string custAddress {get; set;}
    public string custEmail {get; set;}
    public string cartId {get; set; }

    public override String ToString()
    {
        return "\n{\n\torderId : " + orderId +
                  "\n\tcustName : " + custName +
                  "\n\tcustAddress : " + custAddress +
                  "\n\tcustEmail : " + custEmail +
                  "\n\tcartId : " + cartId + "\n}";
    }
}

可以使用相对路径与 #load 指令:

  • #load "mylogger.csx" 加载函数文件夹中的文件。
  • #load "loadedfiles\mylogger.csx" 加载文件函数文件夹中的文件夹。
  • #load "..\shared\mylogger.csx" 在同一级别(即 wwwroot 的正下方)加载文件夹中的文件,使其成为函数文件夹。

#load 指令仅适用于 .csx 文件,不适用于 .cs 文件。

绑定到方法返回值

可通过在 function.json 中使用名称 $return 将方法返回值用于输出绑定。

{
    "name": "$return",
    "type": "blob",
    "direction": "out",
    "path": "output-container/{id}"
}

下面是使用返回值的 C# 脚本代码,后接异步示例:

public static string Run(WorkItem input, ILogger log)
{
    string json = string.Format("{{ \"id\": \"{0}\" }}", input.Id);
    log.LogInformation($"C# script processed queue message. Item={json}");
    return json;
}
public static Task<string> Run(WorkItem input, ILogger log)
{
    string json = string.Format("{{ \"id\": \"{0}\" }}", input.Id);
    log.LogInformation($"C# script processed queue message. Item={json}");
    return Task.FromResult(json);
}

仅当成功的函数执行始终将返回值传递给输出绑定时,才使用返回值。 否则,请使用 ICollectorIAsyncCollector,如以下部分所示。

写入多个输出值

若要将多个值写入输出绑定,或者如果成功的函数调用可能无法将任何内容传递给输出绑定,请使用 ICollectorIAsyncCollector 类型。 这些类型是只写集合,当方法完成时写入输出绑定。

此示例使用 ICollector 将多个队列消息写入到同一队列:

public static void Run(ICollector<string> myQueue, ILogger log)
{
    myQueue.Add("Hello");
    myQueue.Add("World!");
}

日志记录

若要使用 C# 将输出记录到流式传输日志中,请包括 ILogger 类型的参数。 建议将其命名为 log。 避免在 Azure Functions 中使用 Console.Write

public static void Run(string myBlob, ILogger log)
{
    log.LogInformation($"C# Blob trigger function processed: {myBlob}");
}

注意

有关可以代替 TraceWriter 使用的更新日志框架的信息,请参阅 .NET 类库开发人员指南中的 ILogger 文档。

自定义指标日志记录

可以使用 ILogger 上的 LogMetric 扩展方法来在 Application Insights 中创建自定义指标。 下面是示例方法调用:

logger.LogMetric("TestMetric", 1234);

此代码是一种替代方法,使用适用于 .NET 的 Application Insights API 调用 TrackMetric

异步

要使函数异步,请使用 async 关键字并返回 Task 对象。

public async static Task ProcessQueueMessageAsync(
        string blobName,
        Stream blobInput,
        Stream blobOutput)
{
    await blobInput.CopyToAsync(blobOutput, 4096);
}

不能在异步函数中使用 out 参数。 对于输出绑定,请改用函数返回值收集器对象

取消令牌

函数可以接受 CancellationToken 参数,以使操作系统能够在函数即将终止时通知代码。 可以使用此通知来确保该函数不会意外终止,导致数据处于不一致状态。

下面的示例演示了如何检查即将发生的函数终止。

using System;
using System.IO;
using System.Threading;

public static void Run(
    string inputText,
    TextWriter logger,
    CancellationToken token)
{
    for (int i = 0; i < 100; i++)
    {
        if (token.IsCancellationRequested)
        {
            logger.WriteLine("Function was cancelled at iteration {0}", i);
            break;
        }
        Thread.Sleep(5000);
        logger.WriteLine("Normal processing for queue message={0}", inputText);
    }
}

导入命名空间

如果需要导入命名空间,则可使用 using 子句,按正常情况处理。

using System.Net;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

public static Task<HttpResponseMessage> Run(HttpRequestMessage req, ILogger log)

会自动导入以下命名空间,而且是可选的:

  • System
  • System.Collections.Generic
  • System.IO
  • System.Linq
  • System.Net.Http
  • System.Threading.Tasks
  • Microsoft.Azure.WebJobs
  • Microsoft.Azure.WebJobs.Host

引用外部程序集

对于框架程序集,通过使用 #r "AssemblyName" 指令添加引用。

#r "System.Web.Http"

using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

public static Task<HttpResponseMessage> Run(HttpRequestMessage req, ILogger log)

由 Azure 函数主机环境自动添加以下程序集:

  • mscorlib
  • System
  • System.Core
  • System.Xml
  • System.Net.Http
  • Microsoft.Azure.WebJobs
  • Microsoft.Azure.WebJobs.Host
  • Microsoft.Azure.WebJobs.Extensions
  • System.Web.Http
  • System.Net.Http.Formatting

可按运行时版本通过简单名称引用以下程序集:

  • Newtonsoft.Json
  • Microsoft.WindowsAzure.Storage*

*已在运行时版本 4.x 中移除。

在代码中,如下例所示引用程序集:

#r "AssemblyName"

引用自定义程序集

若要引用自定义程序集,可使用共享程序集或私有程序集 :

  • 共享程序集在函数应用内的所有函数中共享。 若要引用自定义程序集,请将程序集上传到函数应用根文件夹 (wwwroot) 中名为“bin”的文件夹。

  • 私有程序集是给定函数上下文的一部分,支持不同版本的旁加载。 私有程序集应上传到函数目录中的 bin 文件夹。 使用文件名(例如 #r "MyAssembly.dll")引用程序集。

有关如何将文件上传到函数文件夹的信息,请参阅有关程序包管理的部分。

监视的目录

自动监视包含函数脚本文件的目录的程序集更改。 若要监视其他目录中的程序集更改,请将其添加到 host.json 中的 watchDirectories 列表中。

使用 NuGet 包

将绑定扩展包和其他 NuGet 包添加到函数应用的方式取决于 Functions 运行时的目标版本

默认情况下,通过使用扩展捆绑包将支持的一组 Functions 扩展 NuGet 包提供给 C# 脚本函数应用。 若要了解详细信息,请参阅扩展捆绑包

如果你出于某种原因而无法在项目中使用扩展捆绑包,则还可以使用 Azure Functions Core Tools 根据应用的 function.json 文件中定义的绑定来安装扩展。 使用 Core Tools 注册扩展时,请确保使用 --csx 选项。 若要了解详细信息,请参阅 func extensions install

默认情况下,Core Tools 会读取 function.json 文件,并将所需的包添加到函数应用的文件系统根目录 (wwwroot) 中的 extensions.csproj C# 类库项目文件。 由于 Core Tools 使用 dotnet.exe,因此你可以使用它添加对此扩展文件的任何 NuGet 包引用。 在安装期间,Core Tools 会生成 extensions.csproj 以安装所需的库。 下面是 extensions.csproj 文件示例,它添加了对 Microsoft.ProjectOxford.Face 1.1.0 版的引用:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Microsoft.ProjectOxford.Face" Version="1.1.0" />
    </ItemGroup>
</Project>

注意

对于 C# 脚本 (.csx),必须将 TargetFramework 设置为值 netstandard2.0。 不支持 net6.0 等其他目标框架。

若要使用自定义 NuGet 源,请在函数应用根文件夹中指定 Nuget.Config 文件中的源。 有关详细信息,请参阅配置 NuGet 行为

如果仅在门户中处理项目,则需要直接在站点中手动创建 extensions.csproj 文件或 Nuget.Config 文件。 若要了解详细信息,请参阅手动安装扩展

环境变量

若要获取环境变量或应用设置值,请使用 System.Environment.GetEnvironmentVariable,如以下代码示例所示:

public static void Run(TimerInfo myTimer, ILogger log)
{
    log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
    log.LogInformation(GetEnvironmentVariable("AzureWebJobsStorage"));
    log.LogInformation(GetEnvironmentVariable("WEBSITE_SITE_NAME"));
}

public static string GetEnvironmentVariable(string name)
{
    return name + ": " +
        System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process);
}

重试策略

Functions 支持两个内置重试策略。 有关详细信息,请参阅重试策略

下面是 function.json 文件中的重试策略:

{
    "disabled": false,
    "bindings": [
        {
            ....
        }
    ],
    "retry": {
        "strategy": "fixedDelay",
        "maxRetryCount": 4,
        "delayInterval": "00:00:10"
    }
}
“function.json”属性 说明
strategy 请使用 fixedDelay
maxRetryCount 必需。 每个函数执行允许的最大重试次数。 -1 表示无限重试。
delayInterval 在重试之间使用的延迟。 将其指定为一个格式为 HH:mm:ss 的字符串。

在运行时绑定

在 C# 和其他 .NET 语言中,可以使用命令性绑定模式,而不是 function.json 中的声明式绑定。 当绑定参数需要在运行时(而非在设计时)计算时,命令性绑定很有用。 通过此模式,可以在函数代码中动态绑定到受支持的输入和输出绑定。

如下所示定义命令性绑定:

  • 对于所需的命令性绑定,不要包含 function.json 中的条目。
  • 传递输入参数 Binder binderIBinder binder
  • 使用下面的 C# 模式执行数据绑定。
using (var output = await binder.BindAsync<T>(new BindingTypeAttribute(...)))
{
    ...
}

BindingTypeAttribute 是定义了绑定的 .NET 属性,T 是该绑定类型所支持的输入或输出类型。 T 不能是 out 参数类型(例如 out JObject)。 例如,移动应用表输出绑定支持 6 种输出类型,但对于 T,只能使用 ICollector<T>IAsyncCollector<T>

单属性示例

下面的示例代码使用在运行时定义的 blob 路径创建存储 blob 输出绑定,然后将字符串写入此 blob。

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host.Bindings.Runtime;

public static async Task Run(string input, Binder binder)
{
    using (var writer = await binder.BindAsync<TextWriter>(new BlobAttribute("samples-output/path")))
    {
        writer.Write("Hello World!!");
    }
}

BlobAttribute 定义存储 blob 输入或输出绑定,TextWriter 是支持的输出绑定类型。

多属性示例

上一个示例获取函数应用的主存储帐户连接字符串(即 AzureWebJobsStorage)的应用设置。 通过添加 StorageAccountAttribute 和将属性数组传入 BindAsync<T>(),可指定要用于存储帐户的自定义应用设置。 使用一个 Binder 参数而非 IBinder。 例如:

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host.Bindings.Runtime;

public static async Task Run(string input, Binder binder)
{
    var attributes = new Attribute[]
    {
        new BlobAttribute("samples-output/path"),
        new StorageAccountAttribute("MyStorageAccount")
    };

    using (var writer = await binder.BindAsync<TextWriter>(attributes))
    {
        writer.Write("Hello World!");
    }
}

下表列出了每种绑定类型的 .NET 属性及其定义所在的包。

将 C# 脚本应用转换为 C# 项目

将 C# 脚本函数应用转换为已编译的 C# 类库项目的最简单方法是从新项目开始。 然后,对于每个函数,可以将代码和配置从函数文件夹中的每个 run.csx 文件和 function.json 文件迁移到单个新的 .cs 类库代码文件。 例如,当你有一个名为 HelloWorld 的 C# 脚本函数时,你将有两个文件:HelloWorld/run.csxHelloWorld/function.json。 对于此函数,请在新的类库项目中创建一个名为 HelloWorld.cs 的代码文件。

如果使用 C# 脚本进行门户编辑,则可以将应用内容下载到本地计算机。 选择“网站内容”选项,而不是“内容和 Visual Studio 项目”。 你无需生成项目,也无需在下载中包含应用程序设置。 你正在定义新的开发环境,此环境的权限不应与托管的应用环境相同。

这些说明演示如何将(使用 Functions 主机在进程内运行的)C# 脚本函数转换为在独立工作进程中运行的 C# 类库函数。

  1. 完成首选快速入门中的“创建函数应用项目”部分:


  1. 如果原始 C# 脚本代码包含 extensions.csproj 文件或任何 function.proj 文件,请复制这些文件中的包引用,并在与 Functions 核心依赖项相同的 ItemGroup 中将其添加到新项目的 .csproj 文件中。

    提示

    转换为更新到最新版本的依赖项提供了一个好机会。 这样做可能需要在后面的步骤中进行其他代码更改。

  2. 将原始 host.json 文件的内容复制到新项目的 host.json 文件中,但 extensionBundles 部分除外(编译后的 C# 项目不使用 扩展捆绑包,因此必须明确添加对函数使用的所有扩展的引用)。 在合并 host.json 文件时,请记住 host.json 架构进行了版本控制,大多数应用使用版本 2.0。 extensions 部分的内容可能因函数使用的绑定扩展的具体版本而异。 请参阅各个扩展参考文章,了解如何为特定版本正确配置 host.json。

  3. 对于 #load 指令引用的任何共享文件,请为每个共享引用创建一个新的 .cs 文件。 最简单的是为每个共享类定义创建一个新的 .cs 文件。 如果存在没有类的静态方法,则需要为这些方法定义新类。

  4. 对原始项目中的每个 <FUNCTION_NAME> 文件夹执行以下任务:

    1. 创建名为 <FUNCTION_NAME>.cs 的新文件,将 <FUNCTION_NAME> 替换为定义 C# 脚本函数的文件夹的名称。 可以通过以下方式根据触发器特定的模板之一创建新的函数代码文件:

      在提示符下使用 func new --name <FUNCTION_NAME> 命令并选择正确的触发器模板。

    2. 复制 run.csx 文件中的 using 语句,并将其添加到新文件中。 无需任何 #r 指令。

    3. 对于 run.csx 文件中的任何 #load 语句,请为用于共享代码的命名空间添加新的 using 语句。

    4. 在新文件中,在用于项目的命名空间下为函数定义类。

    5. 创建一个名为 RunHandler 或类似名称的新方法。 此新方法用作函数的新入口点。

    6. 将表示函数的静态方法以及它调用 run.csx 的任何函数作为第二个方法复制到新类中。 在上一步中创建的新方法中,调用此静态方法。 此间接步骤有助于在继续升级时导航任何差异。 可以保持原始方法完全相同,只需从新上下文控制其输入即可。 可能需要在传递到静态方法调用的新方法上创建参数。 确认迁移已按预期工作后,可以删除此额外的间接级别。

    7. 对于文件中的每个 function.json 绑定,请将相应的属性添加到新方法。 若要快速查找绑定示例,请参阅基于示例手动添加绑定

    8. 将绑定所需的任何扩展包添加到项目(如果尚未这样做)。

  5. local.settings.json 文件Values 集合中重新创建应用所需的任何应用程序设置。

  6. 验证项目是否在本地运行:

    使用 func start 从命令行运行应用。 有关详细信息,请参阅在本地运行函数

  7. 将项目发布到 Azure 中的新函数应用:

    使用 func azure functionapp publish <APP_NAME> 命令创建 Azure 资源并将代码项目部署到 Azure。 有关详细信息,请参阅部署项目文件

示例函数转换

本部分演示单个函数的迁移示例。

C# 脚本中的原始函数有两个文件:

  • HelloWorld/function.json
  • HelloWorld/run.csx

HelloWorld/function.json 的内容是:

{
  "bindings": [
    {
      "authLevel": "FUNCTION",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    }
  ]
}

HelloWorld/run.csx 的内容是:

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string name = req.Query["name"];

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    name = name ?? data?.name;

    string responseMessage = string.IsNullOrEmpty(name)
        ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                : $"Hello, {name}. This HTTP triggered function executed successfully.";

            return new OkObjectResult(responseMessage);
}

迁移到具有 ASP.NET Core集成的隔离辅助角色模型后,这些模型将被替换为单个 HelloWorld.cs

using System.Net;
using Microsoft.Azure.Functions.Worker;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

namespace MyFunctionApp
{
    public class HelloWorld
    {
        private readonly ILogger _logger;

        public HelloWorld(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<HelloWorld>();
        }

        [Function("HelloWorld")]
        public async Task<IActionResult> RunHandler([HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req)
        {
            return await Run(req, _logger);
        }

        // From run.csx
        public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            string responseMessage = string.IsNullOrEmpty(name)
                ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                        : $"Hello, {name}. This HTTP triggered function executed successfully.";

            return new OkObjectResult(responseMessage);
        }
    }
}

绑定配置和示例

本部分包含用于在 C# 脚本中定义触发器和绑定的引用和示例。

Blob 触发器

下表解释了在 function.json 文件中设置的 C# 脚本的绑定配置属性。

function.json 属性 说明
type 必须设置为 blobTrigger。 在 Azure 门户中创建触发器时,会自动设置此属性。
direction 必须设置为 in。 在 Azure 门户中创建触发器时,会自动设置此属性。
name 表示函数代码中的 Blob 的变量的名称。
路径 要监视的容器。 可以是某种 Blob 名称模式
连接 指定如何连接到 Azure Blob 的应用设置或设置集合的名称。 请参阅连接

以下示例显示了 function.json 文件中的一个 blob 触发器定义以及使用该绑定的代码。 在 samples-workitems 容器中添加或更新 Blob 时,该函数会写入一条日志。

下面是 function.json 文件中的绑定数据:

{
    "disabled": false,
    "bindings": [
        {
            "name": "myBlob",
            "type": "blobTrigger",
            "direction": "in",
            "path": "samples-workitems/{name}",
            "connection":"MyStorageAccountAppSetting"
        }
    ]
}

blob 触发器路径 samples-workitems/{name} 中的字符串 {name} 会创建一个绑定表达式,可以在函数代码中使用它来访问触发 blob 的文件名。 有关详细信息,请参阅 Blob 名称模式

下面是绑定到 Stream 的 C# 脚本代码:

public static void Run(Stream myBlob, string name, ILogger log)
{
   log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
}

下面是绑定到 CloudBlockBlob 的 C# 脚本代码:

#r "Microsoft.WindowsAzure.Storage"

using Microsoft.WindowsAzure.Storage.Blob;

public static void Run(CloudBlockBlob myBlob, string name, ILogger log)
{
    log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name}\nURI:{myBlob.StorageUri}");
}

Blob 输入

下表解释了在 function.json 文件中设置的 C# 脚本的绑定配置属性。

function.json 属性 说明
type 必须设置为 blob
direction 必须设置为 in
name 表示函数代码中的 Blob 的变量的名称。
路径 Blob 的路径。
连接 指定如何连接到 Azure Blob 的应用设置或设置集合的名称。 请参阅连接

下面的示例展示了 function.json 文件中的 blob 输入和输出绑定,以及使用这些绑定的 C# 脚本代码。 此函数创建文本 blob 的副本。 该函数由包含要复制的 Blob 名称的队列消息触发。 新 Blob 名为 {originalblobname}-Copy

function.json 文件中,queueTrigger 元数据属性用于指定 path 属性中的 Blob 名称:

{
  "bindings": [
    {
      "queueName": "myqueue-items",
      "connection": "MyStorageConnectionAppSetting",
      "name": "myQueueItem",
      "type": "queueTrigger",
      "direction": "in"
    },
    {
      "name": "myInputBlob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "in"
    },
    {
      "name": "myOutputBlob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}-Copy",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "out"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

public static void Run(string myQueueItem, string myInputBlob, out string myOutputBlob, ILogger log)
{
    log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
    myOutputBlob = myInputBlob;
}

Blob 输出

下表解释了在 function.json 文件中设置的 C# 脚本的绑定配置属性。

function.json 属性 说明
type 必须设置为 blob
direction 必须设置为 out
name 表示函数代码中的 Blob 的变量的名称。
路径 Blob 的路径。
连接 指定如何连接到 Azure Blob 的应用设置或设置集合的名称。 请参阅连接

下面的示例展示了 function.json 文件中的 blob 输入和输出绑定,以及使用这些绑定的 C# 脚本代码。 此函数创建文本 blob 的副本。 该函数由包含要复制的 Blob 名称的队列消息触发。 新 Blob 名为 {originalblobname}-Copy

function.json 文件中,queueTrigger 元数据属性用于指定 path 属性中的 Blob 名称:

{
  "bindings": [
    {
      "queueName": "myqueue-items",
      "connection": "MyStorageConnectionAppSetting",
      "name": "myQueueItem",
      "type": "queueTrigger",
      "direction": "in"
    },
    {
      "name": "myInputBlob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "in"
    },
    {
      "name": "myOutputBlob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}-Copy",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "out"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

public static void Run(string myQueueItem, string myInputBlob, out string myOutputBlob, ILogger log)
{
    log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
    myOutputBlob = myInputBlob;
}

RabbitMQ 触发器

以下示例演示 function.json 文件中的一个 RabbitMQ 触发器绑定以及使用该绑定的 C# 脚本函数。 此函数读取并记录 RabbitMQ 消息。

下面是 function.json 文件中的绑定数据:

{​​
    "bindings": [
        {​​
            "name": "myQueueItem",
            "type": "rabbitMQTrigger",
            "direction": "in",
            "queueName": "queue",
            "connectionStringSetting": "rabbitMQConnectionAppSetting"
        }​​
    ]
}​​

C# 脚本代码如下所示:

using System;

public static void Run(string myQueueItem, ILogger log)
{​​
    log.LogInformation($"C# Script RabbitMQ trigger function processed: {​​myQueueItem}​​");
}​​

队列触发器

下表解释了在 function.json 文件中设置的 C# 脚本的绑定配置属性。

function.json 属性 说明
type 必须设置为 queueTrigger。 在 Azure 门户中创建触发器时,会自动设置此属性。
direction 只能在 function.json 文件中设置。 必须设置为 in。 在 Azure 门户中创建触发器时,会自动设置此属性。
name 函数代码中包含队列项有效负载的变量的名称。
queueName 要轮询的队列的名称。
连接 指定如何连接到 Azure 队列的应用设置或设置集合的名称。 请参阅连接

以下示例演示了 function.json 文件中的一个队列触发器绑定以及使用该绑定的 C# 脚本代码。 每次处理某个队列项之后,该函数会轮询 myqueue-items 队列并写入日志。

function.json 文件如下所示:

{
    "disabled": false,
    "bindings": [
        {
            "type": "queueTrigger",
            "direction": "in",
            "name": "myQueueItem",
            "queueName": "myqueue-items",
            "connection":"MyStorageConnectionAppSetting"
        }
    ]
}

C# 脚本代码如下所示:

#r "Microsoft.WindowsAzure.Storage"

using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage.Queue;
using System;

public static void Run(CloudQueueMessage myQueueItem, 
    DateTimeOffset expirationTime, 
    DateTimeOffset insertionTime, 
    DateTimeOffset nextVisibleTime,
    string queueTrigger,
    string id,
    string popReceipt,
    int dequeueCount,
    ILogger log)
{
    log.LogInformation($"C# Queue trigger function processed: {myQueueItem.AsString}\n" +
        $"queueTrigger={queueTrigger}\n" +
        $"expirationTime={expirationTime}\n" +
        $"insertionTime={insertionTime}\n" +
        $"nextVisibleTime={nextVisibleTime}\n" +
        $"id={id}\n" +
        $"popReceipt={popReceipt}\n" + 
        $"dequeueCount={dequeueCount}");
}

队列输出

下表解释了在 function.json 文件中设置的 C# 脚本的绑定配置属性。

function.json 属性 说明
type 必须设置为 queue。 在 Azure 门户中创建触发器时,会自动设置此属性。
direction 必须设置为 out。 在 Azure 门户中创建触发器时,会自动设置此属性。
name 表示函数代码中的队列的变量的名称。 设置为 $return 可引用函数返回值。
queueName 队列的名称。
连接 指定如何连接到 Azure 队列的应用设置或设置集合的名称。 请参阅连接

以下示例演示了 function.json 文件中的一个 HTTP 触发器绑定以及使用该绑定的 C# 脚本代码。 该函数针对收到的每个 HTTP 请求创建一个包含 CustomQueueMessage 对象有效负载的队列项

function.json 文件如下所示:

{
  "bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "authLevel": "function",
      "name": "input"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    },
    {
      "type": "queue",
      "direction": "out",
      "name": "$return",
      "queueName": "outqueue",
      "connection": "MyStorageConnectionAppSetting"
    }
  ]
}

下面是可创建一条队列消息的 C# 脚本代码:

public class CustomQueueMessage
{
    public string PersonName { get; set; }
    public string Title { get; set; }
}

public static CustomQueueMessage Run(CustomQueueMessage input, ILogger log)
{
    return input;
}

可以使用 ICollectorIAsyncCollector 参数一次性发送多条消息。 以下 C# 脚本代码发送多条消息,其中一条消息包含 HTTP 请求数据,另一条消息包含硬编码值:

public static void Run(
    CustomQueueMessage input, 
    ICollector<CustomQueueMessage> myQueueItems, 
    ILogger log)
{
    myQueueItems.Add(input);
    myQueueItems.Add(new CustomQueueMessage { PersonName = "You", Title = "None" });
}

表输入

本部分仅概述对扩展的表 API 版本的支持。

下表解释了在 function.json 文件中设置的 C# 脚本的绑定配置属性。

function.json 属性 说明
type 必须设置为 table。 在 Azure 门户中创建绑定时,会自动设置此属性。
direction 必须设置为 in。 在 Azure 门户中创建绑定时,会自动设置此属性。
name 表示函数代码中的表或实体的变量的名称。
tableName 表的名称。
partitionKey 可选。 要读取的表实体的分区键。
rowKey 可选。 要读取的表实体的行键。 不能与 takefilter 一起使用。
take 可选。 要返回的实体的最大数目。 无法与 rowKey 一起使用。
filter 可选。 用于从表中返回实体的 OData 筛选器表达式。 无法与 rowKey 一起使用。
连接 指定如何连接到表服务的应用设置或设置集合的名称。 请参阅连接

以下示例演示了 function.json 文件中的一个表输入绑定以及使用该绑定的 C# 脚本代码。 该函数使用队列触发器来读取单个表行。

function.json 文件指定 partitionKeyrowKeyrowKey{queueTrigger} 指示行键来自队列消息字符串。

{
  "bindings": [
    {
      "queueName": "myqueue-items",
      "connection": "MyStorageConnectionAppSetting",
      "name": "myQueueItem",
      "type": "queueTrigger",
      "direction": "in"
    },
    {
      "name": "personEntity",
      "type": "table",
      "tableName": "Person",
      "partitionKey": "Test",
      "rowKey": "{queueTrigger}",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "in"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

#r "Azure.Data.Tables"
using Microsoft.Extensions.Logging;
using Azure.Data.Tables;

public static void Run(string myQueueItem, Person personEntity, ILogger log)
{
    log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
    log.LogInformation($"Name in Person entity: {personEntity.Name}");
}

public class Person : ITableEntity
{
    public string Name { get; set; }

    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public DateTimeOffset? Timestamp { get; set; }
    public ETag ETag { get; set; }
}

表输出

本部分仅概述对扩展的表 API 版本的支持。

下表解释了在 function.json 文件中设置的 C# 脚本的绑定配置属性。

function.json 属性 说明
type 必须设置为 table。 在 Azure 门户中创建绑定时,会自动设置此属性。
direction 必须设置为 out。 在 Azure 门户中创建绑定时,会自动设置此属性。
name 在函数代码中使用的、表示表或实体的变量名称。 设置为 $return 可引用函数返回值。
tableName 要向其写入的表的名称。
partitionKey 要写入的表实体的分区键。
rowKey 要写入的表实体的行键。
连接 指定如何连接到表服务的应用设置或设置集合的名称。 请参阅连接

以下示例演示 function.json 文件中的一个表输出绑定以及使用该绑定的 C# 脚本代码。 该函数写入多个表实体。

function.json 文件如下所示:

{
  "bindings": [
    {
      "name": "input",
      "type": "manualTrigger",
      "direction": "in"
    },
    {
      "tableName": "Person",
      "connection": "MyStorageConnectionAppSetting",
      "name": "tableBinding",
      "type": "table",
      "direction": "out"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

public static void Run(string input, ICollector<Person> tableBinding, ILogger log)
{
    for (int i = 1; i < 10; i++)
        {
            log.LogInformation($"Adding Person entity {i}");
            tableBinding.Add(
                new Person() { 
                    PartitionKey = "Test", 
                    RowKey = i.ToString(), 
                    Name = "Name" + i.ToString() }
                );
        }

}

public class Person
{
    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public string Name { get; set; }
}

计时器触发器

下表解释了在 function.json 文件中设置的 C# 脚本的绑定配置属性。

function.json 属性 说明
type 必须设置为 timerTrigger。 在 Azure 门户中创建触发器时,会自动设置此属性。
direction 必须设置为 in。 在 Azure 门户中创建触发器时,会自动设置此属性。
name 在函数代码中表示计时器对象的变量的名称。
schedule CRON 表达式TimeSpan 值。 只能对在应用服务计划中运行的函数应用使用 TimeSpan。 可以将计划表达式放在应用设置中并将此属性设置为用 % 符号括起的应用设置名称,例如此示例中的“%ScheduleAppSetting%”。
runOnStartup 如果为 true,则在运行时启动时调用此函数。 例如,当函数应用从由于无活动而进入的空闲状态醒来后,运行时会启动。 当函数应用由于函数更改而重新启动时,以及当函数应用横向扩展时。请谨慎使用。runOnStartup 应该很少设置为 true(如果曾经设置过),特别是在生产环境中。
useMonitor 设置为 truefalse 以指示是否应当监视计划。 计划监视在各次计划发生后会持续存在,以帮助确保即使在函数应用实例重新启动的情况下也能正确维护计划。 如果未显式设置,则对于重复周期间隔大于或等于 1 分钟的计划,默认值为 true。 对于每分钟触发多次的计划,默认值为 false

以下示例演示 function.json 文件中的一个计时器触发器绑定以及使用该绑定的 C# 脚本函数。 该函数将写入日志信息,指示调用此函数是由于错过了计划发生时间。 TimerInfo 对象将传递到函数中。

下面是 function.json 文件中的绑定数据:

{
    "schedule": "0 */5 * * * *",
    "name": "myTimer",
    "type": "timerTrigger",
    "direction": "in"
}

C# 脚本代码如下所示:

public static void Run(TimerInfo myTimer, ILogger log)
{
    if (myTimer.IsPastDue)
    {
        log.LogInformation("Timer is running late!");
    }
    log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}" );  
}

HTTP 触发器

下表解释了在 function.json 文件中设置的触发器配置属性:

“function.json”属性 说明
type 必需 - 必须设置为 httpTrigger
direction 必需 - 必须设置为 in
name 必需 - 在请求或请求正文的函数代码中使用的变量名称。
authLevel 确定请求中需要提供的密钥(如果有),以便调用此函数。 有关支持的值,请参阅授权级别
methods HTTP Methods的数组,该函数将响应此Methods。 如果未指定,该函数将响应所有 HTTP Methods。 请参阅自定义 HTTP 终结点
route 定义路由模板,控制函数将响应的请求 URL。 如果未提供任何值,则默认值为 <functionname>。 有关详细信息,请参阅自定义 HTTP 终结点
webHookType 仅支持 1.x 版运行时。

将 HTTP 触发器配置为充当指定提供程序的 webhook 接收器。 有关支持的值,请参阅 WebHook 类型

以下示例演示 function.json 文件中的一个触发器绑定以及使用该绑定的 C# 脚本函数。 该函数在查询字符串或 HTTP 请求的正文中查找 name 参数。

function.json 文件如下所示:

{
    "disabled": false,
    "bindings": [
        {
            "authLevel": "function",
            "name": "req",
            "type": "httpTrigger",
            "direction": "in",
            "methods": [
                "get",
                "post"
            ]
        },
        {
            "name": "$return",
            "type": "http",
            "direction": "out"
        }
    ]
}

下面是绑定到 HttpRequest 的 C# 脚本代码:

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string name = req.Query["name"];
    
    string requestBody = String.Empty;
    using (StreamReader streamReader =  new  StreamReader(req.Body))
    {
        requestBody = await streamReader.ReadToEndAsync();
    }
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    name = name ?? data?.name;
    
    return name != null
        ? (ActionResult)new OkObjectResult($"Hello, {name}")
        : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}

可以绑定到自定义对象而不是 HttpRequest。 此对象从请求正文进行创建,并分析为 JSON。 同样,可以将类型传递给 HTTP 响应输出绑定,并作为响应正文随 200 状态代码一同返回。

using System.Net;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

public static string Run(Person person, ILogger log)
{   
    return person.Name != null
        ? (ActionResult)new OkObjectResult($"Hello, {person.Name}")
        : new BadRequestObjectResult("Please pass an instance of Person.");
}

public class Person {
     public string Name {get; set;}
}

HTTP 输出

下表解释了在 function.json 文件中设置的绑定配置属性。

属性 说明
type 必须设置为 http
direction 必须设置为 out
name 在响应的函数代码中使用的变量名称,或者 $return 以使用返回值。

事件中心触发器

下表解释了在 function.json 文件中设置的触发器配置属性:

“function.json”属性 说明
type 必须设置为 eventHubTrigger。 在 Azure 门户中创建触发器时,会自动设置此属性。
direction 必须设置为 in。 在 Azure 门户中创建触发器时,会自动设置此属性。
name 在函数代码中表示事件项的变量的名称。
eventHubName Functions 2.x 及更高版本。 事件中心的名称。 当事件中心名称也出现在连接字符串中时,该值会在运行时覆盖此属性。 可以通过应用设置 %eventHubName% 进行引用。 在版本 1.x 中,此属性名为 path
consumerGroup 一个可选属性,用于设置使用者组,该组用于订阅事件中心中的事件。 如果将其省略,则会使用 $Default 使用者组。
连接 指定如何连接到事件中心的应用设置或设置集合的名称。 请参阅连接

以下示例演示 function.json 文件中的一个事件中心触发器绑定以及使用该绑定的 C# 脚本函数。 该函数记录事件中心触发器的消息正文。

以下示例显示了 Functions 运行时版本 2.x 及更高版本的 function.json 文件中的事件中心绑定数据。

{
  "type": "eventHubTrigger",
  "name": "myEventHubMessage",
  "direction": "in",
  "eventHubName": "MyEventHub",
  "connection": "myEventHubReadConnectionAppSetting"
}

C# 脚本代码如下所示:

using System;

public static void Run(string myEventHubMessage, TraceWriter log)
{
    log.Info($"C# function triggered to process a message: {myEventHubMessage}");
}

若要在函数代码中访问事件元数据,请绑定到 EventData 对象。 此外,还可以通过在方法签名中使用绑定表达式来访问相同的属性。 以下示例演示了获取相同数据的两种方法:

#r "Microsoft.Azure.EventHubs"

using System.Text;
using System;
using Microsoft.ServiceBus.Messaging;
using Microsoft.Azure.EventHubs;

public void Run(EventData myEventHubMessage,
    DateTime enqueuedTimeUtc,
    Int64 sequenceNumber,
    string offset,
    TraceWriter log)
{
    log.Info($"Event: {Encoding.UTF8.GetString(myEventHubMessage.Body)}");
    log.Info($"EnqueuedTimeUtc={myEventHubMessage.SystemProperties.EnqueuedTimeUtc}");
    log.Info($"SequenceNumber={myEventHubMessage.SystemProperties.SequenceNumber}");
    log.Info($"Offset={myEventHubMessage.SystemProperties.Offset}");

    // Metadata accessed by using binding expressions
    log.Info($"EnqueuedTimeUtc={enqueuedTimeUtc}");
    log.Info($"SequenceNumber={sequenceNumber}");
    log.Info($"Offset={offset}");
}

若要成批接收事件,请将 stringEventData 设为数组:

public static void Run(string[] eventHubMessages, TraceWriter log)
{
    foreach (var message in eventHubMessages)
    {
        log.Info($"C# function triggered to process a message: {message}");
    }
}

事件中心输出

下表解释了在 function.json 文件中设置的绑定配置属性。

“function.json”属性 说明
type 必须设置为 eventHub
direction 必须设置为 out。 在 Azure 门户中创建绑定时,会自动设置该参数。
name 函数代码中使用的表示事件的变量名称。
eventHubName Functions 2.x 及更高版本。 事件中心的名称。 当事件中心名称也出现在连接字符串中时,该值会在运行时覆盖此属性。 在 Functions 1.x 中,此属性名为 path
连接 指定如何连接到事件中心的应用设置或设置集合的名称。 若要了解详细信息,请参阅连接

以下示例演示 function.json 文件中的一个事件中心触发器绑定以及使用该绑定的 C# 脚本函数。 该函数将消息写入事件中心。

以下示例显示了 Functions 运行时版本 2.x 及更高版本的 function.json 文件中的事件中心绑定数据。

{
    "type": "eventHub",
    "name": "outputEventHubMessage",
    "eventHubName": "myeventhub",
    "connection": "MyEventHubSendAppSetting",
    "direction": "out"
}

下面是可创建一条消息的 C# 脚本代码:

using System;
using Microsoft.Extensions.Logging;

public static void Run(TimerInfo myTimer, out string outputEventHubMessage, ILogger log)
{
    String msg = $"TimerTriggerCSharp1 executed at: {DateTime.Now}";
    log.LogInformation(msg);   
    outputEventHubMessage = msg;
}

下面是可创建多条消息的 C# 脚本代码:

public static void Run(TimerInfo myTimer, ICollector<string> outputEventHubMessage, ILogger log)
{
    string message = $"Message created at: {DateTime.Now}";
    log.LogInformation(message);
    outputEventHubMessage.Add("1 " + message);
    outputEventHubMessage.Add("2 " + message);
}

事件网格触发器

下表解释了在 function.json 文件中设置的 C# 脚本的绑定配置属性。 无法在 EventGridTrigger 特性中设置任何构造函数参数或属性。

function.json 属性 说明
type 必需 - 必须设置为 eventGridTrigger
direction 必需 - 必须设置为 in
name 必需 - 在函数代码中对接收事件数据的参数使用的变量名称。

以下示例显示 function.json 文件中定义的事件网格触发器。

下面是 function.json 文件中的绑定数据:

{
  "bindings": [
    {
      "type": "eventGridTrigger",
      "name": "eventGridEvent",
      "direction": "in"
    }
  ],
  "disabled": false
}

下面是使用 EventGridEvent 绑定参数的 C# 脚本函数的示例:

#r "Azure.Messaging.EventGrid"
using Azure.Messaging.EventGrid;
using Microsoft.Extensions.Logging;

public static void Run(EventGridEvent eventGridEvent, ILogger log)
{
    log.LogInformation(eventGridEvent.Data.ToString());
}

下面是使用 JObject 绑定参数的 C# 脚本函数的示例:

#r "Newtonsoft.Json"

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public static void Run(JObject eventGridEvent, TraceWriter log)
{
    log.Info(eventGridEvent.ToString(Formatting.Indented));
}

事件网格输出

下表解释了在 function.json 文件中设置的 C# 脚本的绑定配置属性。

function.json 属性 说明
type 必须设置为 eventGrid
direction 必须设置为 out。 在 Azure 门户中创建绑定时,会自动设置该参数。
name 函数代码中使用的表示事件的变量名称。
topicEndpointUri 包含自定义主题 URI 的应用设置的名称,例如 MyTopicEndpointUri
topicKeySetting 包含自定义主题访问密钥的应用设置的名称。

以下示例显示了 function.json 文件中的事件网格输出绑定数据。

{
    "type": "eventGrid",
    "name": "outputEvent",
    "topicEndpointUri": "MyEventGridTopicUriSetting",
    "topicKeySetting": "MyEventGridTopicKeySetting",
    "direction": "out"
}

以下 C# 脚本代码将创建一个事件:

#r "Microsoft.Azure.EventGrid"
using System;
using Microsoft.Azure.EventGrid.Models;
using Microsoft.Extensions.Logging;

public static void Run(TimerInfo myTimer, out EventGridEvent outputEvent, ILogger log)
{
    outputEvent = new EventGridEvent("message-id", "subject-name", "event-data", "event-type", DateTime.UtcNow, "1.0");
}

以下 C# 脚本代码将创建多个事件:

#r "Microsoft.Azure.EventGrid"
using System;
using Microsoft.Azure.EventGrid.Models;
using Microsoft.Extensions.Logging;

public static void Run(TimerInfo myTimer, ICollector<EventGridEvent> outputEvent, ILogger log)
{
    outputEvent.Add(new EventGridEvent("message-id-1", "subject-name", "event-data", "event-type", DateTime.UtcNow, "1.0"));
    outputEvent.Add(new EventGridEvent("message-id-2", "subject-name", "event-data", "event-type", DateTime.UtcNow, "1.0"));
}

服务总线触发器

下表解释了在 function.json 文件中设置的绑定配置属性。

“function.json”属性 说明
type 必须设置为 serviceBusTrigger。 在 Azure 门户中创建触发器时,会自动设置此属性。
direction 必须设置为 in。 在 Azure 门户中创建触发器时,会自动设置此属性。
name 变量的名称,表示函数代码中的队列或主题消息。
queueName 要监视的队列的名称。 仅在监视队列的情况下设置,不为主题设置。
topicName 要监视的主题的名称。 仅在监视主题的情况下设置,不为队列设置。
subscriptionName 要监视的订阅的名称。 仅在监视主题的情况下设置,不为队列设置。
连接 指定如何连接到服务总线的应用设置或设置集合的名称。 请参阅连接
accessRights 连接字符串的访问权限。 可用值为 managelisten。 默认值是 manage,其指示 connection 具有“管理”权限。 如果使用不具有“管理”权限的连接字符串,请将 accessRights 设置为“listen”。 否则,Functions 运行时可能会在尝试执行需要管理权限的操作时失败。 在 Azure Functions 版本 2.x 及更高版本中,此属性不可用,因为最新版本的服务总线 SDK 不支持管理操作。
isSessionsEnabled 如果连接到会话感知队列或订阅,则为 true。 否则为 false(默认值)。
autoComplete 如果触发器应在处理后自动调用 complete,或者你会通过函数代码手动调用 complete,则此项为 true

仅在 C# 中支持将其设置为 false

如果设置为 true,则触发器会在函数执行成功完成时自动完成该消息,否则会放弃该消息。
<br/如果设置为 false,你负责调用 ServiceBusReceiver 方法来完成、放弃消息、会话或批,或将它们放入死信队列。 如果引发了异常(并且未调用任何 ServiceBusReceiver 方法),则锁仍然存在。 锁到期后,消息会重新排队,同时 DeliveryCount 会递增,并且锁会自动续订。

此属性仅在 Azure Functions 2.x 和更高版本中可用。

以下示例演示 function.json 文件中的一个服务总线触发器绑定以及使用该绑定的 C# 脚本函数。 此函数将读取消息元数据并记录服务总线队列消息。

下面是 function.json 文件中的绑定数据:

{
"bindings": [
    {
    "queueName": "testqueue",
    "connection": "MyServiceBusConnection",
    "name": "myQueueItem",
    "type": "serviceBusTrigger",
    "direction": "in"
    }
],
"disabled": false
}

C# 脚本代码如下所示:

using System;

public static void Run(string myQueueItem,
    Int32 deliveryCount,
    DateTime enqueuedTimeUtc,
    string messageId,
    TraceWriter log)
{
    log.Info($"C# ServiceBus queue trigger function processed message: {myQueueItem}");

    log.Info($"EnqueuedTimeUtc={enqueuedTimeUtc}");
    log.Info($"DeliveryCount={deliveryCount}");
    log.Info($"MessageId={messageId}");
}

服务总线输出

下表解释了在 function.json 文件中设置的绑定配置属性。

“function.json”属性 说明
type 必须设置为 serviceBus。 在 Azure 门户中创建触发器时,会自动设置此属性。
direction 必须设置为 out。 在 Azure 门户中创建触发器时,会自动设置此属性。
name 变量的名称,表示函数代码中的队列或主题消息。 设置为“$return”可引用函数返回值。
queueName 队列名称。 仅在发送队列消息的情况下设置,不为主题设置。
topicName 主题名称。 仅在发送主题消息的情况下设置,不为队列设置。
连接 指定如何连接到服务总线的应用设置或设置集合的名称。 请参阅连接
accessRights(仅限 v1) 连接字符串的访问权限。 可用值为 managelisten。 默认值是 manage,其指示 connection 具有“管理”权限。 如果使用不具有“管理”权限的连接字符串,请将 accessRights 设置为“listen”。 否则,Functions 运行时可能会在尝试执行需要管理权限的操作时失败。 在 Azure Functions 版本 2.x 及更高版本中,此属性不可用,因为最新版本的服务总线 SDK 不支持管理操作。

以下示例演示 function.json 文件中的一个服务总线输出绑定以及使用该绑定的 C# 脚本函数。 该函数使用计时器触发器,每隔 15 秒发送一条队列消息。

下面是 function.json 文件中的绑定数据:

{
    "bindings": [
        {
            "schedule": "0/15 * * * * *",
            "name": "myTimer",
            "runsOnStartup": true,
            "type": "timerTrigger",
            "direction": "in"
        },
        {
            "name": "outputSbQueue",
            "type": "serviceBus",
            "queueName": "testqueue",
            "connection": "MyServiceBusConnection",
            "direction": "out"
        }
    ],
    "disabled": false
}

下面是可创建一条消息的 C# 脚本代码:

public static void Run(TimerInfo myTimer, ILogger log, out string outputSbQueue)
{
    string message = $"Service Bus queue message created at: {DateTime.Now}";
    log.LogInformation(message); 
    outputSbQueue = message;
}

下面是可创建多条消息的 C# 脚本代码:

public static async Task Run(TimerInfo myTimer, ILogger log, IAsyncCollector<string> outputSbQueue)
{
    string message = $"Service Bus queue messages created at: {DateTime.Now}";
    log.LogInformation(message); 
    await outputSbQueue.AddAsync("1 " + message);
    await outputSbQueue.AddAsync("2 " + message);
}

Azure Cosmos DB v2 触发器

本部分仅概述对扩展的版本 4.x+ 的支持。

下表解释了在 function.json 文件中设置的绑定配置属性。

“function.json”属性 说明
type 必须设置为 cosmosDBTrigger
direction 必须设置为 in。 在 Azure 门户中创建触发器时,会自动设置该参数。
name 函数代码中使用的变量名称,表示发生更改的文档列表。
连接 应用设置或设置集合的名称,用于指定如何连接到受监视的 Azure Cosmos DB 帐户。 有关详细信息,请参阅连接
databaseName 带有受监视的容器的 Azure Cosmos DB 数据库的名称。
containerName 要监视的容器的名称。
leaseConnectionStringSetting (可选)应用设置或设置容器的名称,用于指定如何连接到保留租用容器的 Azure Cosmos DB 帐户。

未设置时,使用 ConnectionStringSetting 值。 在门户中创建绑定时,将自动设置该参数。 用于租用容器的连接字符串必须具有写入权限。
leaseDatabaseName (可选)数据库的名称,该数据库包含用于存储租用的容器。 未设置时,使用 databaseName 设置的值。
leaseContainerName (可选)用于存储租约的容器的名称。 未设置时,使用值 leases
createLeaseContainerIfNotExists (可选)设置为 true 时,如果租用容器并不存在,将自动创建该集合。 默认值为 false。 在使用 Azure AD 标识时,如果将值设为 true,创建容器就不是受允许的操作,且无法启动函数。
leasesContainerThroughput (可选)在创建租用容器时,定义要分配的请求单位的数量。 仅当 createLeaseContainerIfNotExists 设置为 true 时,才会使用此设置。 使用门户创建绑定时,将自动设置该参数。
leaseContainerPrefix (可选)设置后,该值将作为前缀添加到在此函数的租用容器中创建的租约。 使用前缀可让两个不同的 Azure 函数通过不同的前缀来共享同一个租用容器。
feedPollDelay (可选)在所有当前更改清空后,每两次在分区中轮询源上的新更改的延迟时间(以毫秒为单位)。 默认值为 5,000 毫秒(5 秒)。
leaseAcquireInterval (可选)设置后,此项以毫秒为单位定义启动一个计算任务的时间间隔(前提是分区在已知的主机实例中均匀分布)。 默认为 13000(13 秒)。
leaseExpirationInterval (可选)设置后,此项以毫秒为单位定义在表示分区的租用上进行租用的时间间隔。 如果在此时间间隔内不续订租用,则该租用会过期,分区的所有权会转移到另一个实例。 默认为 60000(60 秒)。
leaseRenewInterval (可选)设置后,此项以毫秒为单位定义当前由实例拥有的分区的所有租用的续订时间间隔。 默认为 17000(17 秒)。
maxItemsPerInvocation (可选)设置后,此属性会对每次函数调用收到的项目的最大数目进行设置。 如果受监视容器中的操作通过存储过程执行,则在从更改源读取项时,会保留事务范围。 因此,收到的项数可能高于指定的值,通过同一事务更改的项会通过某个原子批处理操作返回。
startFromBeginning (可选)此选项告知触发器要从容器的更改历史记录开头位置读取更改,而不是从当前时间开始读取。 从开头位置读取仅在触发器首次启动时起作用,因为在后续运行中,已存储检查点。 如果已经创建租约,则将此选项设置为 true 将不起作用。
startFromTime (可选)获取或设置初始化更改源读取操作的日期和时间。 建议使用具有 UTC 指示符的 ISO 8601 格式,例如 2021-02-16T14:19:29Z。 这仅用于设置初始触发器状态。 触发器具有租用状态后,更改此值将不起作用。
preferredLocations (可选)为 Azure Cosmos DB 服务中的异地复制数据库帐户定义首选位置(区域)。 值应以逗号分隔。 例如,“中国北部,中国北部,中国北部”。

以下示例演示 function.json 文件中的 Azure Cosmos DB 触发器绑定以及使用该绑定的 C# 脚本函数。 添加或修改 Azure Cosmos DB 记录时,该函数会写入日志消息。

下面是 function.json 文件中的绑定数据:

{
    "type": "cosmosDBTrigger",
    "name": "documents",
    "direction": "in",
    "leaseContainerName": "leases",
    "connection": "<connection-app-setting>",
    "databaseName": "Tasks",
    "containerName": "Items",
    "createLeaseContainerIfNotExists": true
}

C# 脚本代码如下所示:

    using System;
    using System.Collections.Generic;
    using Microsoft.Extensions.Logging;

    // Customize the model with your own desired properties
    public class ToDoItem
    {
        public string id { get; set; }
        public string Description { get; set; }
    }

    public static void Run(IReadOnlyList<ToDoItem> documents, ILogger log)
    {
      log.LogInformation("Documents modified " + documents.Count);
      log.LogInformation("First document Id " + documents[0].id);
    }

Azure Cosmos DB v2 输入

本部分仅概述对扩展的版本 4.x+ 的支持。

下表解释了在 function.json 文件中设置的绑定配置属性。

“function.json”属性 说明
type 必须设置为 cosmosDB
direction 必须设置为 in
name 函数代码中使用的变量名称,表示发生更改的文档列表。
连接 应用设置或设置容器的名称,用于指定如何连接到受监视的 Azure Cosmos DB 帐户。 有关详细信息,请参阅连接
databaseName 带有受监视的容器的 Azure Cosmos DB 数据库的名称。
containerName 要监视的容器的名称。
partitionKey 指定用于查找分区键值。 可以包含绑定参数。 它是在分区的容器中进行查询所需的。
id 要检索的文档的 ID。 此属性支持绑定表达式。 不要同时设置 idsqlQuery 属性。 如果上述两个属性都未设置,则会检索整个容器。
sqlQuery 用于检索多个文档的 Azure Cosmos DB SQL 查询。 该属性支持运行时绑定,如以下示例中所示:SELECT * FROM c where c.departmentId = {departmentId}。 不要同时设置 idsqlQuery 属性。 如果上述两个属性都未设置,则会检索整个容器。
preferredLocations (可选)为 Azure Cosmos DB 服务中的异地复制数据库帐户定义首选位置(区域)。 值应以逗号分隔。 例如 China East,China North,China North 2

本部分包含以下示例:

HTTP 触发器示例引用简单的 ToDoItem 类型:

namespace CosmosDBSamplesV2
{
    public class ToDoItem
    {
        public string Id { get; set; }
        public string Description { get; set; }
    }
}

队列触发器,从字符串查找 ID

以下示例演示 function.json 文件中的一个 Azure Cosmos DB 输入绑定以及使用该绑定的 C# 脚本函数。 该函数读取单个文档,并更新文档的文本值。

下面是 function.json 文件中的绑定数据:

{
    "name": "inputDocument",
    "type": "cosmosDB",
    "databaseName": "MyDatabase",
    "collectionName": "MyCollection",
    "id" : "{queueTrigger}",
    "partitionKey": "{partition key value}",
    "connectionStringSetting": "MyAccount_COSMOSDB",
    "direction": "in"
}

C# 脚本代码如下所示:

    using System;

    // Change input document contents using Azure Cosmos DB input binding
    public static void Run(string myQueueItem, dynamic inputDocument)
    {
      inputDocument.text = "This has changed.";
    }

队列触发器,使用 SqlQuery 获取多个文档

以下示例演示 function.json 文件中的一个 Azure Cosmos DB 输入绑定以及使用该绑定的 C# 脚本函数。 该函数使用队列触发器自定义查询参数检索 SQL 查询指定的多个文档。

队列触发器提供参数 departmentId{ "departmentId" : "Finance" } 的队列消息将返回财务部的所有记录。

下面是 function.json 文件中的绑定数据:

{
    "name": "documents",
    "type": "cosmosDB",
    "direction": "in",
    "databaseName": "MyDb",
    "collectionName": "MyCollection",
    "sqlQuery": "SELECT * from c where c.departmentId = {departmentId}",
    "connectionStringSetting": "CosmosDBConnection"
}

C# 脚本代码如下所示:

    public static void Run(QueuePayload myQueueItem, IEnumerable<dynamic> documents)
    {
        foreach (var doc in documents)
        {
            // operate on each document
        }
    }

    public class QueuePayload
    {
        public string departmentId { get; set; }
    }

HTTP 触发器,从查询字符串查找 ID

以下示例演示检索单个文档的 C# 脚本函数。 此函数由 HTTP 请求触发,该请求使用的查询字符串用于指定要查找的 ID 和分区键值。 该 ID 和分区键值用于从指定的数据库和集合中检索 ToDoItem 文档。

function.json 文件如下所示:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "cosmosDB",
      "name": "toDoItem",
      "databaseName": "ToDoItems",
      "collectionName": "Items",
      "connectionStringSetting": "CosmosDBConnection",
      "direction": "in",
      "Id": "{Query.id}",
      "PartitionKey" : "{Query.partitionKeyValue}"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

using System.Net;
using Microsoft.Extensions.Logging;

public static HttpResponseMessage Run(HttpRequestMessage req, ToDoItem toDoItem, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    if (toDoItem == null)
    {
         log.LogInformation($"ToDo item not found");
    }
    else
    {
        log.LogInformation($"Found ToDo item, Description={toDoItem.Description}");
    }
    return req.CreateResponse(HttpStatusCode.OK);
}

HTTP 触发器,从路由数据查找 ID

以下示例演示检索单个文档的 C# 脚本函数。 此函数由 HTTP 请求触发,该请求使用的路由数据用于指定要查找的 ID 和分区键值。 该 ID 和分区键值用于从指定的数据库和集合中检索 ToDoItem 文档。

function.json 文件如下所示:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
        "get",
        "post"
      ],
      "route":"todoitems/{partitionKeyValue}/{id}"
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "cosmosDB",
      "name": "toDoItem",
      "databaseName": "ToDoItems",
      "collectionName": "Items",
      "connectionStringSetting": "CosmosDBConnection",
      "direction": "in",
      "id": "{id}",
      "partitionKey": "{partitionKeyValue}"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

using System.Net;
using Microsoft.Extensions.Logging;

public static HttpResponseMessage Run(HttpRequestMessage req, ToDoItem toDoItem, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    if (toDoItem == null)
    {
         log.LogInformation($"ToDo item not found");
    }
    else
    {
        log.LogInformation($"Found ToDo item, Description={toDoItem.Description}");
    }
    return req.CreateResponse(HttpStatusCode.OK);
}

HTTP 触发器,使用 SqlQuery 获取多个文档

以下示例演示检索文档列表的 C# 脚本函数。 此函数由 HTTP 请求触发。 此查询在 SqlQuery 特性属性中指定。

function.json 文件如下所示:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "cosmosDB",
      "name": "toDoItems",
      "databaseName": "ToDoItems",
      "collectionName": "Items",
      "connectionStringSetting": "CosmosDBConnection",
      "direction": "in",
      "sqlQuery": "SELECT top 2 * FROM c order by c._ts desc"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

using System.Net;
using Microsoft.Extensions.Logging;

public static HttpResponseMessage Run(HttpRequestMessage req, IEnumerable<ToDoItem> toDoItems, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    foreach (ToDoItem toDoItem in toDoItems)
    {
        log.LogInformation(toDoItem.Description);
    }
    return req.CreateResponse(HttpStatusCode.OK);
}

HTTP 触发器,使用 DocumentClient 获取多个文档

以下示例演示检索文档列表的 C# 脚本函数。 此函数由 HTTP 请求触发。 此代码使用 Azure Cosmos DB 绑定提供的 DocumentClient 实例来读取文档列表。 DocumentClient 实例也可用于写入操作。

function.json 文件如下所示:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "cosmosDB",
      "name": "client",
      "databaseName": "ToDoItems",
      "collectionName": "Items",
      "connectionStringSetting": "CosmosDBConnection",
      "direction": "inout"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

#r "Microsoft.Azure.Documents.Client"

using System.Net;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Microsoft.Extensions.Logging;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, DocumentClient client, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    Uri collectionUri = UriFactory.CreateDocumentCollectionUri("ToDoItems", "Items");
    string searchterm = req.GetQueryNameValuePairs()
        .FirstOrDefault(q => string.Compare(q.Key, "searchterm", true) == 0)
        .Value;

    if (searchterm == null)
    {
        return req.CreateResponse(HttpStatusCode.NotFound);
    }

    log.LogInformation($"Searching for word: {searchterm} using Uri: {collectionUri.ToString()}");
    IDocumentQuery<ToDoItem> query = client.CreateDocumentQuery<ToDoItem>(collectionUri)
        .Where(p => p.Description.Contains(searchterm))
        .AsDocumentQuery();

    while (query.HasMoreResults)
    {
        foreach (ToDoItem result in await query.ExecuteNextAsync())
        {
            log.LogInformation(result.Description);
        }
    }
    return req.CreateResponse(HttpStatusCode.OK);
}

Azure Cosmos DB v2 输出

本部分仅概述对扩展的版本 4.x+ 的支持。

下表解释了在 function.json 文件中设置的绑定配置属性。

“function.json”属性 说明
连接 应用设置或设置集合的名称,用于指定如何连接到受监视的 Azure Cosmos DB 帐户。 有关详细信息,请参阅连接
databaseName 带有受监视的容器的 Azure Cosmos DB 数据库的名称。
containerName 要监视的容器的名称。
createIfNotExists 一个用于指示是否创建容器(如果不存在)的布尔值。 默认值为 false,因为新容器是使用保留的吞吐量创建的,具有成本方面的隐含意义。 有关详细信息,请参阅定价页
partitionKey createIfNotExists 为 true 时,它定义所创建容器的分区键路径。 可以包含绑定参数。
containerThroughput createIfNotExists 为 true 时,它定义所创建容器的吞吐量
preferredLocations (可选)为 Azure Cosmos DB 服务中的异地复制数据库帐户定义首选位置(区域)。 值应以逗号分隔。 例如 China North,China North,China North

本部分包含以下示例:

队列触发器,写入一个文档

以下示例演示 function.json 文件中的一个 Azure Cosmos DB 输出绑定以及使用该绑定的 C# 脚本函数。 该函数使用一个用于某个队列的队列输入绑定,该队列以下列格式接收 JSON:

{
    "name": "John Henry",
    "employeeId": "123456",
    "address": "A town nearby"
}

该函数按下列格式为每个记录创建 Azure Cosmos DB 文档:

{
    "id": "John Henry-123456",
    "name": "John Henry",
    "employeeId": "123456",
    "address": "A town nearby"
}

下面是 function.json 文件中的绑定数据:

{
    "name": "employeeDocument",
    "type": "cosmosDB",
    "databaseName": "MyDatabase",
    "collectionName": "MyCollection",
    "createIfNotExists": true,
    "connectionStringSetting": "MyAccount_COSMOSDB",
    "direction": "out"
}

C# 脚本代码如下所示:

    #r "Newtonsoft.Json"

    using Microsoft.Azure.WebJobs.Host;
    using Newtonsoft.Json.Linq;
    using Microsoft.Extensions.Logging;

    public static void Run(string myQueueItem, out object employeeDocument, ILogger log)
    {
      log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");

      dynamic employee = JObject.Parse(myQueueItem);

      employeeDocument = new {
        id = employee.name + "-" + employee.employeeId,
        name = employee.name,
        employeeId = employee.employeeId,
        address = employee.address
      };
    }

队列触发器,使用 IAsyncCollector 来写入文档

若要创建多个文档,可以绑定到 ICollector<T>IAsyncCollector<T>,其中 T 是受支持的类型之一。

此示例引用简单的 ToDoItem 类型:

namespace CosmosDBSamplesV2
{
    public class ToDoItem
    {
        public string id { get; set; }
        public string Description { get; set; }
    }
}

function.json 文件如下所示:

{
  "bindings": [
    {
      "name": "toDoItemsIn",
      "type": "queueTrigger",
      "direction": "in",
      "queueName": "todoqueueforwritemulti",
      "connectionStringSetting": "AzureWebJobsStorage"
    },
    {
      "type": "cosmosDB",
      "name": "toDoItemsOut",
      "databaseName": "ToDoItems",
      "collectionName": "Items",
      "connectionStringSetting": "CosmosDBConnection",
      "direction": "out"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

using System;
using Microsoft.Extensions.Logging;

public static async Task Run(ToDoItem[] toDoItemsIn, IAsyncCollector<ToDoItem> toDoItemsOut, ILogger log)
{
    log.LogInformation($"C# Queue trigger function processed {toDoItemsIn?.Length} items");

    foreach (ToDoItem toDoItem in toDoItemsIn)
    {
        log.LogInformation($"Description={toDoItem.Description}");
        await toDoItemsOut.AddAsync(toDoItem);
    }
}

Azure Cosmos DB v1 触发器

以下示例演示 function.json 文件中的 Azure Cosmos DB 触发器绑定以及使用该绑定的 C# 脚本函数。 修改 Azure Cosmos DB 记录时,该函数会写入日志消息。

下面是 function.json 文件中的绑定数据:

{
    "type": "cosmosDBTrigger",
    "name": "documents",
    "direction": "in",
    "leaseCollectionName": "leases",
    "connectionStringSetting": "<connection-app-setting>",
    "databaseName": "Tasks",
    "collectionName": "Items",
    "createLeaseCollectionIfNotExists": true
}

C# 脚本代码如下所示:

    #r "Microsoft.Azure.Documents.Client"
    
    using System;
    using Microsoft.Azure.Documents;
    using System.Collections.Generic;
    

    public static void Run(IReadOnlyList<Document> documents, TraceWriter log)
    {
        log.Info("Documents modified " + documents.Count);
        log.Info("First document Id " + documents[0].Id);
    }

Azure Cosmos DB v1 输入

本部分包含以下示例:

HTTP 触发器示例引用简单的 ToDoItem 类型:

namespace CosmosDBSamplesV1
{
    public class ToDoItem
    {
        public string Id { get; set; }
        public string Description { get; set; }
    }
}

队列触发器,从字符串查找 ID

以下示例演示 function.json 文件中的一个 Azure Cosmos DB 输入绑定以及使用该绑定的 C# 脚本函数。 该函数读取单个文档,并更新文档的文本值。

下面是 function.json 文件中的绑定数据:

{
    "name": "inputDocument",
    "type": "documentDB",
    "databaseName": "MyDatabase",
    "collectionName": "MyCollection",
    "id" : "{queueTrigger}",
    "partitionKey": "{partition key value}",
    "connection": "MyAccount_COSMOSDB",
    "direction": "in"
}

C# 脚本代码如下所示:

    using System;

    // Change input document contents using Azure Cosmos DB input binding
    public static void Run(string myQueueItem, dynamic inputDocument)
    {
        inputDocument.text = "This has changed.";
    }

队列触发器,使用 SqlQuery 获取多个文档

以下示例演示 function.json 文件中的一个 Azure Cosmos DB 输入绑定以及使用该绑定的 C# 脚本函数。 该函数使用队列触发器自定义查询参数检索 SQL 查询指定的多个文档。

队列触发器提供参数 departmentId{ "departmentId" : "Finance" } 的队列消息将返回财务部的所有记录。

下面是 function.json 文件中的绑定数据:

{
    "name": "documents",
    "type": "documentdb",
    "direction": "in",
    "databaseName": "MyDb",
    "collectionName": "MyCollection",
    "sqlQuery": "SELECT * from c where c.departmentId = {departmentId}",
    "connection": "CosmosDBConnection"
}

C# 脚本代码如下所示:

    public static void Run(QueuePayload myQueueItem, IEnumerable<dynamic> documents)
    {
        foreach (var doc in documents)
        {
            // operate on each document
        }
    }

    public class QueuePayload
    {
        public string departmentId { get; set; }
    }

HTTP 触发器,从查询字符串查找 ID

以下示例演示检索单个文档的 C# 脚本函数。 此函数由一个 HTTP 请求触发,该请求使用查询字符串指定要查找的 ID。 该 ID 用于从指定的数据库和集合检索 ToDoItem 文档。

function.json 文件如下所示:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "documentDB",
      "name": "toDoItem",
      "databaseName": "ToDoItems",
      "collectionName": "Items",
      "connection": "CosmosDBConnection",
      "direction": "in",
      "Id": "{Query.id}"
    }
  ],
  "disabled": true
}

C# 脚本代码如下所示:

using System.Net;

public static HttpResponseMessage Run(HttpRequestMessage req, ToDoItem toDoItem, TraceWriter log)
{
    log.Info("C# HTTP trigger function processed a request.");

    if (toDoItem == null)
    {
        log.Info($"ToDo item not found");
    }
    else
    {
        log.Info($"Found ToDo item, Description={toDoItem.Description}");
    }
    return req.CreateResponse(HttpStatusCode.OK);
}

HTTP 触发器,从路由数据查找 ID

以下示例演示检索单个文档的 C# 脚本函数。 此函数由 HTTP 请求触发,该请求使用的路由数据用于指定要查找的 ID。 该 ID 用于从指定的数据库和集合检索 ToDoItem 文档。

function.json 文件如下所示:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
        "get",
        "post"
      ],
      "route":"todoitems/{id}"
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "documentDB",
      "name": "toDoItem",
      "databaseName": "ToDoItems",
      "collectionName": "Items",
      "connection": "CosmosDBConnection",
      "direction": "in",
      "Id": "{id}"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

using System.Net;

public static HttpResponseMessage Run(HttpRequestMessage req, ToDoItem toDoItem, TraceWriter log)
{
    log.Info("C# HTTP trigger function processed a request.");

    if (toDoItem == null)
    {
        log.Info($"ToDo item not found");
    }
    else
    {
        log.Info($"Found ToDo item, Description={toDoItem.Description}");
    }
    return req.CreateResponse(HttpStatusCode.OK);
}

HTTP 触发器,使用 SqlQuery 获取多个文档

以下示例演示检索文档列表的 C# 脚本函数。 此函数由 HTTP 请求触发。 此查询在 SqlQuery 特性属性中指定。

function.json 文件如下所示:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "documentDB",
      "name": "toDoItems",
      "databaseName": "ToDoItems",
      "collectionName": "Items",
      "connection": "CosmosDBConnection",
      "direction": "in",
      "sqlQuery": "SELECT top 2 * FROM c order by c._ts desc"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

using System.Net;

public static HttpResponseMessage Run(HttpRequestMessage req, IEnumerable<ToDoItem> toDoItems, TraceWriter log)
{
    log.Info("C# HTTP trigger function processed a request.");

    foreach (ToDoItem toDoItem in toDoItems)
    {
        log.Info(toDoItem.Description);
    }
    return req.CreateResponse(HttpStatusCode.OK);
}

HTTP 触发器,使用 DocumentClient 获取多个文档

以下示例演示检索文档列表的 C# 脚本函数。 此函数由 HTTP 请求触发。 此代码使用 Azure Cosmos DB 绑定提供的 DocumentClient 实例来读取文档列表。 DocumentClient 实例也可用于写入操作。

function.json 文件如下所示:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "documentDB",
      "name": "client",
      "databaseName": "ToDoItems",
      "collectionName": "Items",
      "connection": "CosmosDBConnection",
      "direction": "inout"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

#r "Microsoft.Azure.Documents.Client"

using System.Net;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, DocumentClient client, TraceWriter log)
{
    log.Info("C# HTTP trigger function processed a request.");

    Uri collectionUri = UriFactory.CreateDocumentCollectionUri("ToDoItems", "Items");
    string searchterm = req.GetQueryNameValuePairs()
        .FirstOrDefault(q => string.Compare(q.Key, "searchterm", true) == 0)
        .Value;

    if (searchterm == null)
    {
        return req.CreateResponse(HttpStatusCode.NotFound);
    }

    log.Info($"Searching for word: {searchterm} using Uri: {collectionUri.ToString()}");
    IDocumentQuery<ToDoItem> query = client.CreateDocumentQuery<ToDoItem>(collectionUri)
        .Where(p => p.Description.Contains(searchterm))
        .AsDocumentQuery();

    while (query.HasMoreResults)
    {
        foreach (ToDoItem result in await query.ExecuteNextAsync())
        {
            log.Info(result.Description);
        }
    }
    return req.CreateResponse(HttpStatusCode.OK);
}

Azure Cosmos DB v1 输出

本部分包含以下示例:

  • 队列触发器,写入一个文档
  • 队列触发器,使用 IAsyncCollector 写入文档

队列触发器,写入一个文档

以下示例演示 function.json 文件中的一个 Azure Cosmos DB 输出绑定以及使用该绑定的 C# 脚本函数。 该函数使用一个用于某个队列的队列输入绑定,该队列以下列格式接收 JSON:

{
    "name": "John Henry",
    "employeeId": "123456",
    "address": "A town nearby"
}

该函数按下列格式为每个记录创建 Azure Cosmos DB 文档:

{
    "id": "John Henry-123456",
    "name": "John Henry",
    "employeeId": "123456",
    "address": "A town nearby"
}

下面是 function.json 文件中的绑定数据:

{
    "name": "employeeDocument",
    "type": "documentDB",
    "databaseName": "MyDatabase",
    "collectionName": "MyCollection",
    "createIfNotExists": true,
    "connection": "MyAccount_COSMOSDB",
    "direction": "out"
}

C# 脚本代码如下所示:

    #r "Newtonsoft.Json"

    using Microsoft.Azure.WebJobs.Host;
    using Newtonsoft.Json.Linq;

    public static void Run(string myQueueItem, out object employeeDocument, TraceWriter log)
    {
        log.Info($"C# Queue trigger function processed: {myQueueItem}");

        dynamic employee = JObject.Parse(myQueueItem);

        employeeDocument = new {
            id = employee.name + "-" + employee.employeeId,
            name = employee.name,
            employeeId = employee.employeeId,
            address = employee.address
        };
    }

队列触发器,使用 IAsyncCollector 来写入文档

若要创建多个文档,可以绑定到 ICollector<T>IAsyncCollector<T>,其中 T 是受支持的类型之一。

此示例引用简单的 ToDoItem 类型:

namespace CosmosDBSamplesV1
{
    public class ToDoItem
    {
        public string Id { get; set; }
        public string Description { get; set; }
    }
}

function.json 文件如下所示:

{
  "bindings": [
    {
      "name": "toDoItemsIn",
      "type": "queueTrigger",
      "direction": "in",
      "queueName": "todoqueueforwritemulti",
      "connection": "AzureWebJobsStorage"
    },
    {
      "type": "documentDB",
      "name": "toDoItemsOut",
      "databaseName": "ToDoItems",
      "collectionName": "Items",
      "connection": "CosmosDBConnection",
      "direction": "out"
    }
  ],
  "disabled": false
}

C# 脚本代码如下所示:

using System;

public static async Task Run(ToDoItem[] toDoItemsIn, IAsyncCollector<ToDoItem> toDoItemsOut, TraceWriter log)
{
    log.Info($"C# Queue trigger function processed {toDoItemsIn?.Length} items");

    foreach (ToDoItem toDoItem in toDoItemsIn)
    {
        log.Info($"Description={toDoItem.Description}");
        await toDoItemsOut.AddAsync(toDoItem);
    }
}

Azure SQL 触发器

GitHub 存储库中提供了更多有关 Azure SQL 触发器的示例。

这些示例引用 ToDoItem 类和相应的数据库表:

namespace AzureSQL.ToDo
{
    public class ToDoItem
    {
        public Guid Id { get; set; }
        public int? order { get; set; }
        public string title { get; set; }
        public string url { get; set; }
        public bool? completed { get; set; }
    }
}
CREATE TABLE dbo.ToDo (
    [Id] UNIQUEIDENTIFIER PRIMARY KEY,
    [order] INT NULL,
    [title] NVARCHAR(200) NOT NULL,
    [url] NVARCHAR(200) NOT NULL,
    [completed] BIT NOT NULL
);

数据库和表中启用了更改跟踪

ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);

ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;

SQL 触发器绑定到 IReadOnlyList<SqlChange<T>>,即 SqlChange 对象列表,每个对象具有 2 个属性:

  • 项:已更改的项。 项的类型应遵循 ToDoItem 类中所示的表架构。
  • 操作:SqlChangeOperation 枚举中的值。 可能的值为 InsertUpdateDelete

以下示例显示了 function.json 文件中的 SQL 触发器,以及在 ToDo 表发生更改时调用的 C# 脚本函数

下面是 function.json 文件中的绑定数据:

{
    "name": "todoChanges",
    "type": "sqlTrigger",
    "direction": "in",
    "tableName": "dbo.ToDo",
    "connectionStringSetting": "SqlConnectionString"
}

下面是 C# 脚本函数:

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static void Run(IReadOnlyList<SqlChange<ToDoItem>> todoChanges, ILogger log)
{
    log.LogInformation($"C# SQL trigger function processed a request.");

    foreach (SqlChange<ToDoItem> change in todoChanges)
    {
        ToDoItem toDoItem = change.Item;
        log.LogInformation($"Change operation: {change.Operation}");
        log.LogInformation($"Id: {toDoItem.Id}, Title: {toDoItem.title}, Url: {toDoItem.url}, Completed: {toDoItem.completed}");
    }
}

Azure SQL 输入

GitHub 存储库中提供了更多有关 Azure SQL 输入绑定的示例。

本部分包含以下示例:

这些示例引用 ToDoItem 类和相应的数据库表:

namespace AzureSQL.ToDo
{
    public class ToDoItem
    {
        public Guid Id { get; set; }
        public int? order { get; set; }
        public string title { get; set; }
        public string url { get; set; }
        public bool? completed { get; set; }
    }
}
CREATE TABLE dbo.ToDo (
    [Id] UNIQUEIDENTIFIER PRIMARY KEY,
    [order] INT NULL,
    [title] NVARCHAR(200) NOT NULL,
    [url] NVARCHAR(200) NOT NULL,
    [completed] BIT NOT NULL
);

HTTP 触发器,从查询字符串中按 ID 获取行

以下示例演示 function.json 文件中的一个 Azure SQL 输入绑定以及使用该绑定的 C# 脚本函数。 此函数由 HTTP 请求触发,该请求使用查询字符串来指定 ID。 该 ID 用于使用指定的查询检索 ToDoItem 记录。

注意

HTTP 查询字符串参数区分大小写。

下面是 function.json 文件中的绑定数据:

{
    "authLevel": "anonymous",
    "type": "httpTrigger",
    "direction": "in",
    "name": "req",
    "methods": [
        "get"
    ]
},
{
    "type": "http",
    "direction": "out",
    "name": "res"
},
{
    "name": "todoItem",
    "type": "sql",
    "direction": "in",
    "commandText": "select [Id], [order], [title], [url], [completed] from dbo.ToDo where Id = @Id",
    "commandType": "Text",
    "parameters": "@Id = {Query.id}",
    "connectionStringSetting": "SqlConnectionString"
}

C# 脚本代码如下所示:

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using System.Collections.Generic;

public static IActionResult Run(HttpRequest req, ILogger log, IEnumerable<ToDoItem> todoItem)
{
    return new OkObjectResult(todoItem);
}

HTTP 触发器,删除行

下面的示例演示 function.json 文件和 C# 脚本函数中的 Azure SQL 输入绑定,它使用绑定来执行来自 HTTP 请求查询参数的带输入的存储过程。 此示例中的存储过程根据参数值删除单个记录或所有记录。

必须在 SQL 数据库上创建存储过程 dbo.DeleteToDo

CREATE PROCEDURE [dbo].[DeleteToDo]
    @Id NVARCHAR(100)
AS
    DECLARE @UID UNIQUEIDENTIFIER = TRY_CAST(@ID AS UNIQUEIDENTIFIER)
    IF @UId IS NOT NULL AND @Id != ''
    BEGIN
        DELETE FROM dbo.ToDo WHERE Id = @UID
    END
    ELSE
    BEGIN
        DELETE FROM dbo.ToDo WHERE @ID = ''
    END

    SELECT [Id], [order], [title], [url], [completed] FROM dbo.ToDo
GO

下面是 function.json 文件中的绑定数据:

{
    "authLevel": "anonymous",
    "type": "httpTrigger",
    "direction": "in",
    "name": "req",
    "methods": [
        "get"
    ]
},
{
    "type": "http",
    "direction": "out",
    "name": "res"
},
{
    "name": "todoItems",
    "type": "sql",
    "direction": "in",
    "commandText": "DeleteToDo",
    "commandType": "StoredProcedure",
    "parameters": "@Id = {Query.id}",
    "connectionStringSetting": "SqlConnectionString"
}
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

namespace AzureSQL.ToDo
{
    public static class DeleteToDo
    {
        // delete all items or a specific item from querystring
        // returns remaining items
        // uses input binding with a stored procedure DeleteToDo to delete items and return remaining items
        [FunctionName("DeleteToDo")]
        public static IActionResult Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = "DeleteFunction")] HttpRequest req,
            ILogger log,
            [Sql(commandText: "DeleteToDo", commandType: System.Data.CommandType.StoredProcedure, 
                parameters: "@Id={Query.id}", connectionStringSetting: "SqlConnectionString")] 
                IEnumerable<ToDoItem> toDoItems)
        {
            return new OkObjectResult(toDoItems);
        }
    }
}

C# 脚本代码如下所示:

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using System.Collections.Generic;

public static IActionResult Run(HttpRequest req, ILogger log, IEnumerable<ToDoItem> todoItems)
{
    return new OkObjectResult(todoItems);
}

Azure SQL 输出

GitHub 存储库中提供了更多有关 Azure SQL 输出绑定的示例。

本部分包含以下示例:

这些示例引用 ToDoItem 类和相应的数据库表:

namespace AzureSQL.ToDo
{
    public class ToDoItem
    {
        public Guid Id { get; set; }
        public int? order { get; set; }
        public string title { get; set; }
        public string url { get; set; }
        public bool? completed { get; set; }
    }
}
CREATE TABLE dbo.ToDo (
    [Id] UNIQUEIDENTIFIER PRIMARY KEY,
    [order] INT NULL,
    [title] NVARCHAR(200) NOT NULL,
    [url] NVARCHAR(200) NOT NULL,
    [completed] BIT NOT NULL
);

HTTP 触发器,将记录写入到一个表

以下示例演示了 function.json 文件中的一个 SQL 输出绑定,以及一个 C# 脚本函数,该函数使用 HTTP POST 请求中提供的数据作为 JSON 正文将记录添加到表中。

下面是 function.json 文件中的绑定数据:

{
    "authLevel": "anonymous",
    "type": "httpTrigger",
    "direction": "in",
    "name": "req",
    "methods": [
        "post"
    ]
},
{
    "type": "http",
    "direction": "out",
    "name": "res"
},
{
    "name": "todoItem",
    "type": "sql",
    "direction": "out",
    "commandText": "dbo.ToDo",
    "connectionStringSetting": "SqlConnectionString"
}

下面是示例 C# 脚本代码:

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static IActionResult Run(HttpRequest req, ILogger log, out ToDoItem todoItem)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string requestBody = new StreamReader(req.Body).ReadToEnd();
    todoItem = JsonConvert.DeserializeObject<ToDoItem>(requestBody);

    return new OkObjectResult(todoItem);
}

HTTP 触发器,写入到两个表

以下示例演示了 function.json 文件中的一个 SQL 输出绑定,以及一个 C# 脚本函数,该函数使用 HTTP POST 请求中提供的数据作为 JSON 正文以及多个输出绑定,将记录添加到数据库的两个不同表中(dbo.ToDodbo.RequestLog)。

第二个表 (dbo.RequestLog) 对应于以下定义:

CREATE TABLE dbo.RequestLog (
    Id int identity(1,1) primary key,
    RequestTimeStamp datetime2 not null,
    ItemCount int not null
)

下面是 function.json 文件中的绑定数据:

{
    "authLevel": "anonymous",
    "type": "httpTrigger",
    "direction": "in",
    "name": "req",
    "methods": [
        "post"
    ]
},
{
    "type": "http",
    "direction": "out",
    "name": "res"
},
{
    "name": "todoItem",
    "type": "sql",
    "direction": "out",
    "commandText": "dbo.ToDo",
    "connectionStringSetting": "SqlConnectionString"
},
{
    "name": "requestLog",
    "type": "sql",
    "direction": "out",
    "commandText": "dbo.RequestLog",
    "connectionStringSetting": "SqlConnectionString"
}

下面是示例 C# 脚本代码:

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static IActionResult Run(HttpRequest req, ILogger log, out ToDoItem todoItem, out RequestLog requestLog)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string requestBody = new StreamReader(req.Body).ReadToEnd();
    todoItem = JsonConvert.DeserializeObject<ToDoItem>(requestBody);

    requestLog = new RequestLog();
    requestLog.RequestTimeStamp = DateTime.Now;
    requestLog.ItemCount = 1;

    return new OkObjectResult(todoItem);
}

public class RequestLog {
    public DateTime RequestTimeStamp { get; set; }
    public int ItemCount { get; set; }
}

RabbitMQ 输出

以下示例演示 function.json 文件中的一个 RabbitMQ 输出绑定以及使用该绑定的 C# 脚本函数。 该函数从 HTTP 触发器读取消息,并将其输出到 RabbitMQ 队列。

下面是 function.json 文件中的绑定数据:

{
    "bindings": [
        {
            "type": "httpTrigger",
            "direction": "in",
            "authLevel": "function",
            "name": "input",
            "methods": [
                "get",
                "post"
            ]
        },
        {
            "type": "rabbitMQ",
            "name": "outputMessage",
            "queueName": "outputQueue",
            "connectionStringSetting": "rabbitMQConnectionAppSetting",
            "direction": "out"
        }
    ]
}

C# 脚本代码如下所示:

using System;
using Microsoft.Extensions.Logging;

public static void Run(string input, out string outputMessage, ILogger log)
{
    log.LogInformation(input);
    outputMessage = input;
}

SendGrid 输出

以下示例演示 function.json 文件中的一个 SendGrid 输出绑定以及使用该绑定的 C# 脚本函数

下面是 function.json 文件中的绑定数据:

{
    "bindings": [
        {
          "type": "queueTrigger",
          "name": "mymsg",
          "queueName": "myqueue",
          "connection": "AzureWebJobsStorage",
          "direction": "in"
        },
        {
          "type": "sendGrid",
          "name": "$return",
          "direction": "out",
          "apiKey": "SendGridAPIKeyAsAppSetting",
          "from": "{FromEmail}",
          "to": "{ToEmail}"
        }
    ]
}

C# 脚本代码如下所示:

#r "SendGrid"

using System;
using SendGrid.Helpers.Mail;
using Microsoft.Azure.WebJobs.Host;

public static SendGridMessage Run(Message mymsg, ILogger log)
{
    SendGridMessage message = new SendGridMessage()
    {
        Subject = $"{mymsg.Subject}"
    };
    
    message.AddContent("text/plain", $"{mymsg.Content}");

    return message;
}
public class Message
{
    public string ToEmail { get; set; }
    public string FromEmail { get; set; }
    public string Subject { get; set; }
    public string Content { get; set; }
}

SignalR 触发器

下面是 function.json 文件中的示例绑定数据:

{
    "type": "signalRTrigger",
    "name": "invocation",
    "hubName": "SignalRTest",
    "category": "messages",
    "event": "SendMessage",
    "parameterNames": [
        "message"
    ],
    "direction": "in"
}

然后,代码如下:

#r "Microsoft.Azure.WebJobs.Extensions.SignalRService"
using System;
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
using Microsoft.Extensions.Logging;

public static void Run(InvocationContext invocation, string message, ILogger logger)
{
    logger.LogInformation($"Receive {message} from {invocationContext.ConnectionId}.");
}

SignalR 输入

以下示例演示 function.json 文件中的一个 SignalR 连接信息输入绑定,以及使用该绑定来返回连接信息的 C# Script 函数

下面是 function.json 文件中的绑定数据:

示例 function.json:

{
    "type": "signalRConnectionInfo",
    "name": "connectionInfo",
    "hubName": "chat",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "direction": "in"
}

C# 脚本代码如下所示:

#r "Microsoft.Azure.WebJobs.Extensions.SignalRService"
using Microsoft.Azure.WebJobs.Extensions.SignalRService;

public static SignalRConnectionInfo Run(HttpRequest req, SignalRConnectionInfo connectionInfo)
{
    return connectionInfo;
}

可以使用绑定表达式{headers.x-ms-client-principal-id}{headers.x-ms-client-principal-name} 将绑定的 userId 属性设置为任一标头中的值。

示例 function.json:

{
    "type": "signalRConnectionInfo",
    "name": "connectionInfo",
    "hubName": "chat",
    "userId": "{headers.x-ms-client-principal-id}",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "direction": "in"
}

C# 脚本代码如下所示:

#r "Microsoft.Azure.WebJobs.Extensions.SignalRService"
using Microsoft.Azure.WebJobs.Extensions.SignalRService;

public static SignalRConnectionInfo Run(HttpRequest req, SignalRConnectionInfo connectionInfo)
{
    // connectionInfo contains an access key token with a name identifier
    // claim set to the authenticated user
    return connectionInfo;
}

SignalR 输出

下面是 function.json 文件中的绑定数据:

示例 function.json:

{
  "type": "signalR",
  "name": "signalRMessages",
  "hubName": "<hub_name>",
  "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
  "direction": "out"
}

C# 脚本代码如下所示:

#r "Microsoft.Azure.WebJobs.Extensions.SignalRService"
using Microsoft.Azure.WebJobs.Extensions.SignalRService;

public static Task Run(
    object message,
    IAsyncCollector<SignalRMessage> signalRMessages)
{
    return signalRMessages.AddAsync(
        new SignalRMessage
        {
            Target = "newMessage",
            Arguments = new [] { message }
        });
}

可以设置 SignalR 消息的用户 ID,以便将消息只发送给已针对某个用户进行身份验证的连接。

示例 function.json:

{
  "type": "signalR",
  "name": "signalRMessages",
  "hubName": "<hub_name>",
  "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
  "direction": "out"
}

C# 脚本代码如下所示:

#r "Microsoft.Azure.WebJobs.Extensions.SignalRService"
using Microsoft.Azure.WebJobs.Extensions.SignalRService;

public static Task Run(
    object message,
    IAsyncCollector<SignalRMessage> signalRMessages)
{
    return signalRMessages.AddAsync(
        new SignalRMessage
        {
            // the message will only be sent to this user ID
            UserId = "userId1",
            Target = "newMessage",
            Arguments = new [] { message }
        });
}

可以设置 SignalR 消息的组名称,以便将消息只发送给已添加到某个组的连接。

示例 function.json:

{
  "type": "signalR",
  "name": "signalRMessages",
  "hubName": "<hub_name>",
  "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
  "direction": "out"
}

C# 脚本代码如下所示:

#r "Microsoft.Azure.WebJobs.Extensions.SignalRService"
using Microsoft.Azure.WebJobs.Extensions.SignalRService;

public static Task Run(
    object message,
    IAsyncCollector<SignalRMessage> signalRMessages)
{
    return signalRMessages.AddAsync(
        new SignalRMessage
        {
            // the message will be sent to the group with this name
            GroupName = "myGroup",
            Target = "newMessage",
            Arguments = new [] { message }
        });
}

SignalR 服务允许将用户或连接添加到组中。 然后即可将消息发送到组。 可以使用 SignalR 输出绑定来管理组。

以下示例将用户添加到组。

示例 function.json

{
    "type": "signalR",
    "name": "signalRGroupActions",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "hubName": "chat",
    "direction": "out"
}

Run.csx

#r "Microsoft.Azure.WebJobs.Extensions.SignalRService"
using Microsoft.Azure.WebJobs.Extensions.SignalRService;

public static Task Run(
    HttpRequest req,
    ClaimsPrincipal claimsPrincipal,
    IAsyncCollector<SignalRGroupAction> signalRGroupActions)
{
    var userIdClaim = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier);
    return signalRGroupActions.AddAsync(
        new SignalRGroupAction
        {
            UserId = userIdClaim.Value,
            GroupName = "myGroup",
            Action = GroupAction.Add
        });
}

以下示例从组中删除用户。

示例 function.json

{
    "type": "signalR",
    "name": "signalRGroupActions",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "hubName": "chat",
    "direction": "out"
}

Run.csx

#r "Microsoft.Azure.WebJobs.Extensions.SignalRService"
using Microsoft.Azure.WebJobs.Extensions.SignalRService;

public static Task Run(
    HttpRequest req,
    ClaimsPrincipal claimsPrincipal,
    IAsyncCollector<SignalRGroupAction> signalRGroupActions)
{
    var userIdClaim = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier);
    return signalRGroupActions.AddAsync(
        new SignalRGroupAction
        {
            UserId = userIdClaim.Value,
            GroupName = "myGroup",
            Action = GroupAction.Remove
        });
}

Twilio 输出

以下示例演示 function.json 文件中的一个 Twilio 输出绑定以及使用该绑定的 C# 脚本函数。 该函数使用 out 参数发送短信。

下面是 function.json 文件中的绑定数据:

示例 function.json:

{
  "type": "twilioSms",
  "name": "message",
  "accountSidSetting": "TwilioAccountSid",
  "authTokenSetting": "TwilioAuthToken",
  "from": "+1425XXXXXXX",
  "direction": "out",
  "body": "Azure Functions Testing"
}

C# 脚本代码如下所示:

#r "Newtonsoft.Json"
#r "Twilio"
#r "Microsoft.Azure.WebJobs.Extensions.Twilio"

using System;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.Azure.WebJobs.Extensions.Twilio;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;

public static void Run(string myQueueItem, out CreateMessageOptions message,  ILogger log)
{
    log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");

    // In this example the queue item is a JSON string representing an order that contains the name of a
    // customer and a mobile number to send text updates to.
    dynamic order = JsonConvert.DeserializeObject(myQueueItem);
    string msg = "Hello " + order.name + ", thank you for your order.";

    // You must initialize the CreateMessageOptions variable with the "To" phone number.
    message = new CreateMessageOptions(new PhoneNumber("+1704XXXXXXX"));

    // A dynamic message can be set instead of the body in the output binding. In this example, we use
    // the order information to personalize a text message.
    message.Body = msg;
}

不能在异步代码中使用 out 参数。 下面是异步 C# 脚本代码的示例:

#r "Newtonsoft.Json"
#r "Twilio"
#r "Microsoft.Azure.WebJobs.Extensions.Twilio"

using System;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.Azure.WebJobs.Extensions.Twilio;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;

public static async Task Run(string myQueueItem, IAsyncCollector<CreateMessageOptions> message,  ILogger log)
{
    log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");

    // In this example the queue item is a JSON string representing an order that contains the name of a
    // customer and a mobile number to send text updates to.
    dynamic order = JsonConvert.DeserializeObject(myQueueItem);
    string msg = "Hello " + order.name + ", thank you for your order.";

    // You must initialize the CreateMessageOptions variable with the "To" phone number.
    CreateMessageOptions smsText = new CreateMessageOptions(new PhoneNumber("+1704XXXXXXX"));

    // A dynamic message can be set instead of the body in the output binding. In this example, we use
    // the order information to personalize a text message.
    smsText.Body = msg;

    await message.AddAsync(smsText);
}

预热触发器

下面的示例展示了 function.json 文件中的一个预热触发器和一个 C# 脚本函数,该函数在向应用添加新实例时在每个新实例上运行。

不支持 Functions 运行时版本 1.x。

function.json 文件如下所示:

{
    "bindings": [
        {
            "type": "warmupTrigger",
            "direction": "in",
            "name": "warmupContext"
        }
    ]
}
public static void Run(WarmupContext warmupContext, ILogger log)
{
    log.LogInformation("Function App instance is warm.");  
}

后续步骤