您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

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

本文介绍了如何使用 C# 脚本 ( .csx) 开发 Azure Functions。This article is an introduction to developing Azure Functions by using C# script (.csx).

Azure Functions 支持 C# 和 C# 脚本编程语言。Azure Functions supports C# and C# script programming languages. 如需在 Visual Studio 类库项目中使用 C# 方面的指南,请参阅 C# 开发人员参考If you're looking for guidance on using C# in a Visual Studio class library project, see C# developer reference.

本文假定你已阅读 Azure Functions 开发人员指南This article assumes that you've already read the Azure Functions developers guide.

.csx 的工作原理How .csx works

Azure Functions 的 C# 脚本体验基于 Azure WebJobs SDKThe C# script experience for Azure Functions is based on the Azure WebJobs SDK. 数据通过方法参数流入 C # 函数。Data flows into your C# function via method arguments. 参数名称在 function.json 文件中指定,而预定义的名称则用于访问函数记录器和取消令牌等内容。Argument names are specified in a function.json file, and there are predefined names for accessing things like the function logger and cancellation tokens.

.csx 格式允许编写更少的“样本”,因此你可以集中编写 C# 函数。The .csx format allows you to write less "boilerplate" and focus on writing just a C# function. 只需定义 Run 方法即可,无需将所有内容都包装在命名空间和类中。Instead of wrapping everything in a namespace and class, just define a Run method. 像往常一样,在文件开头包含任何程序集引用和命名空间。Include any assembly references and namespaces at the beginning of the file as usual.

初始化实例时,会编译函数应用的 .csx 文件。A function app's .csx files are compiled when an instance is initialized. 此编译步骤意味着,与 C# 类库相比,冷启动之类的操作对于 C# 脚本函数来说可能需要更长的时间。This compilation step means things like cold start may take longer for C# script functions compared to C# class libraries. 此编译步骤也说明了为何 C# 脚本函数在 Azure 门户中可以编辑,而 C# 类库则不可以编辑。This compilation step is also why C# script functions are editable in the Azure portal, while C# class libraries are not.

文件夹结构Folder structure

C# 脚本项目的文件夹结构如下所示:The folder structure for a C# script project looks like the following:

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

有一个共享的 host.json 文件,可用于配置函数应用。There's a shared host.json file that can be used to configure the function app. 每个函数都具有自己的代码文件 (.csx) 和绑定配置文件 (function.json)。Each function has its own code file (.csx) and binding configuration file (function.json).

2.x 版 Functions 运行时中所需的绑定扩展在 extensions.csproj 文件中定义,实际库文件位于 bin 文件夹中。The binding extensions required in version 2.x of the Functions runtime are defined in the extensions.csproj file, with the actual library files in the bin folder. 本地开发时,必须注册绑定扩展When developing locally, you must register binding extensions. 在 Azure 门户中开发函数时,系统将为你完成此注册。When developing functions in the Azure portal, this registration is done for you.

绑定到参数Binding to arguments

输入或输出数据通过 function.json 配置文件中的 name 属性绑定到 C# 脚本函数参数。Input or output data is bound to a C# script function parameter via the name property in the function.json configuration file. 以下示例显示了一个 function.json 文件以及适用于队列触发函数的 run.csx 文件。The following example shows a function.json file and run.csx file for a queue-triggered function. 从队列消息接收数据的参数名为 myQueueItem,因为这是 name 属性的值。The parameter that receives data from the queue message is named myQueueItem because that's the value of the name property.

{
    "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 语句做了解释。The #r statement is explained later in this article.

绑定支持的类型Supported types for bindings

每个绑定都具有其自己支持的类型;例如,Blob 触发器可以与字符串参数、POCO 参数、CloudBlockBlob 参数或任何其他几种受支持类型之一配合使用。Each binding has its own supported types; for instance, a blob trigger can be used with a string parameter, a POCO parameter, a CloudBlockBlob parameter, or any of several other supported types. 适用于 Blob 绑定的绑定参考文章列出了适用于 Blob 触发器的所有受支持参数类型。The binding reference article for blob bindings lists all supported parameter types for blob triggers. 有关详细信息,请参阅触发器和绑定每个绑定类型的绑定参考文档For more information, see Triggers and bindings and the binding reference docs for each binding type.

提示

如果计划使用 HTTP 或 WebHook 绑定,请制定计划来避免因实例化 HttpClient 不当导致的端口耗尽现象。If you plan to use the HTTP or WebHook bindings, plan to avoid port exhaustion that can be caused by improper instantiation of HttpClient. 有关详细信息,请参阅如何在 Azure Functions 中管理连接For more information, see How to manage connections in Azure Functions.

引用自定义类Referencing custom classes

如需使用自定义的普通旧 CLR 对象 (POCO) 类,可以将类定义包括在同一文件中,也可以将其置于单独的文件中。If you need to use a custom Plain Old CLR Object (POCO) class, you can include the class definition inside the same file or put it in a separate file.

以下示例显示了一个 run.csx 示例,后者包括一个 POCO 类定义。The following example shows a run.csx example that includes a POCO class definition.

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。A POCO class must have a getter and setter defined for each property.

重用.csx 代码Reusing .csx code

可以在 run.csx 文件中使用其他 run.csx 文件中定义的类和方法。You can use classes and methods defined in other .csx files in your run.csx file. 为此,需使用 run.csx 文件中的 #load 指令。To do that, use #load directives in your run.csx file. 在下面的实例中,在 myLogger.csx 中共享了名为 MyLogger 的日志记录例程,并使用 #load 指令将其加载到 run.csx:In the following example, a logging routine named MyLogger is shared in myLogger.csx and loaded into run.csx using the #load directive:

示例 run.csxExample 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.csxExample mylogger.csx:

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

若要使用 POCO 对象强类型化在函数间传递的数据,常见模式是使用共享的 .csx 文件。Using a shared .csx file is a common pattern when you want to strongly type the data passed between functions by using a POCO object. 在下面的简化示例中,一个 HTTP 触发器和队列触发器共享名为 Order 的 POCO 对象以强类型化顺序数据:In the following simplified example, an HTTP trigger and queue trigger share a POCO object named Order to strongly type the order data:

HTTP 触发器的示例 run.csx:Example run.csx for HTTP trigger:

#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:Example run.csx for queue trigger:

#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:Example 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 指令:You can use a relative path with the #load directive:

  • #load "mylogger.csx" 加载函数文件夹中的文件。#load "mylogger.csx" loads a file located in the function folder.
  • #load "loadedfiles\mylogger.csx" 加载文件函数文件夹中的文件夹。#load "loadedfiles\mylogger.csx" loads a file located in a folder in the function folder.
  • #load "..\shared\mylogger.csx" 在同一级别(即 wwwroot 的正下方)加载文件夹中的文件,使其成为函数文件夹。#load "..\shared\mylogger.csx" loads a file located in a folder at the same level as the function folder, that is, directly under wwwroot.

#load 指令仅适用于 .csx 文件,不适用于 .cs 文件。The #load directive works only with .csx files, not with .cs files.

绑定到方法返回值Binding to method return value

可通过在 function.json 中使用名称 $return 将方法返回值用于输出绑定。You can use a method return value for an output binding, by using the name $return in function.json. 有关示例,请参阅触发器和绑定For examples, see Triggers and bindings.

仅当成功的函数执行始终将返回值传递给输出绑定时,才使用返回值。Use the return value only if a successful function execution always results in a return value to pass to the output binding. 否则,请使用 ICollectorIAsyncCollector,如以下部分所示。Otherwise, use ICollector or IAsyncCollector, as shown in the following section.

写入多个输出值Writing multiple output values

若要将多个值写入输出绑定,或者如果成功的函数调用可能无法将任何内容传递给输出绑定,请使用 ICollectorIAsyncCollector 类型。To write multiple values to an output binding, or if a successful function invocation might not result in anything to pass to the output binding, use the ICollector or IAsyncCollector types. 这些类型是只写集合,当方法完成时写入输出绑定。These types are write-only collections that are written to the output binding when the method completes.

此示例使用 ICollector 将多个队列消息写入到同一队列:This example writes multiple queue messages into the same queue using ICollector:

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

日志记录Logging

若要使用 C# 将输出记录到流式传输日志中,请包括 ILogger 类型的参数。To log output to your streaming logs in C#, include an argument of type ILogger. 建议将其命名为 logWe recommend that you name it log. 避免在 Azure Functions 中使用 Console.WriteAvoid using Console.Write in Azure Functions.

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

备注

有关可以用来代替 TraceWriter 的较新的日志记录框架,请参阅监视 Azure Functions 一文中的以 C# 函数写入日志For information about a newer logging framework that you can use instead of TraceWriter, see Write logs in C# functions in the Monitor Azure Functions article.

异步Async

要使函数异步,请使用 async 关键字并返回 Task 对象。To make a function asynchronous, use the async keyword and return a Task object.

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

不能在异步函数中使用 out 参数。You can't use out parameters in async functions. 对于输出绑定,请改用函数返回值收集器对象For output bindings, use the function return value or a collector object instead.

取消令牌Cancellation tokens

函数可以接受 CancellationToken 参数,以使操作系统能够在函数即将终止时通知代码。A function can accept a CancellationToken parameter, which enables the operating system to notify your code when the function is about to be terminated. 可以使用此通知来确保该函数不会意外终止,导致数据处于不一致状态。You can use this notification to make sure the function doesn't terminate unexpectedly in a way that leaves data in an inconsistent state.

下面的示例演示了如何检查即将发生的函数终止。The following example shows how to check for impending function termination.

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

导入命名空间Importing namespaces

如果需要导入命名空间,则可使用 using 子句,按正常情况处理。If you need to import namespaces, you can do so as usual, with the using clause.

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

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

会自动导入以下命名空间,而且是可选的:The following namespaces are automatically imported and are therefore optional:

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

引用外部程序集Referencing external assemblies

对于框架程序集,通过使用 #r "AssemblyName" 指令添加引用。For framework assemblies, add references by using the #r "AssemblyName" directive.

#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 函数主机环境自动添加以下程序集:The following assemblies are automatically added by the Azure Functions hosting environment:

  • 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

可通过简单名称(例如 #r "AssemblyName")引用以下程序集:The following assemblies may be referenced by simple-name (for example, #r "AssemblyName"):

  • Newtonsoft.Json
  • Microsoft.WindowsAzure.Storage
  • Microsoft.ServiceBus
  • Microsoft.AspNet.WebHooks.Receivers
  • Microsoft.AspNet.WebHooks.Common
  • Microsoft.Azure.NotificationHubs

引用自定义程序集Referencing custom assemblies

若要引用自定义程序集,可使用共享程序集或私有程序集:To reference a custom assembly, you can use either a shared assembly or a private assembly:

  • 共享程序集在函数应用内的所有函数中共享。Shared assemblies are shared across all functions within a function app. 若要引用自定义程序集,请将程序集上传到函数应用根文件夹bin (wwwroot) 中名为 的文件夹。To reference a custom assembly, upload the assembly to a folder named bin in your function app root folder (wwwroot).

  • 私有程序集是给定函数上下文的一部分,支持不同版本的旁加载。Private assemblies are part of a given function's context, and support side-loading of different versions. 私有程序集应上传到函数目录中的 bin 文件夹。Private assemblies should be uploaded in a bin folder in the function directory. 使用文件名(例如 #r "MyAssembly.dll")引用程序集。Reference the assemblies using the file name, such as #r "MyAssembly.dll".

有关如何将文件上传到函数文件夹的信息,请参阅有关程序包管理的部分。For information on how to upload files to your function folder, see the section on package management.

监视的目录Watched directories

自动监视包含函数脚本文件的目录的程序集更改。The directory that contains the function script file is automatically watched for changes to assemblies. 若要监视其他目录中的程序集更改,请将其添加到 host.json 中的 watchDirectories 列表中。To watch for assembly changes in other directories, add them to the watchDirectories list in host.json.

使用 NuGet 包Using NuGet packages

若要在 2.x C# 函数中使用 NuGet 包,请将 function.proj 文件上传到函数应用的文件系统中的函数文件夹。To use NuGet packages in a 2.x C# function, upload a function.proj file to the function's folder in the function app's file system. 下面是示例 function.proj 文件,它添加了对 Microsoft.ProjectOxford.Face 1.1.0 版的引用:Here is an example function.proj file that adds a reference to Microsoft.ProjectOxford.Face version 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>

若要使用自定义 NuGet 源,请在 Function App 根中指定“Nuget.Config”文件中的源。To use a custom NuGet feed, specify the feed in a Nuget.Config file in the Function App root. 有关详细信息,请参阅配置 NuGet 行为For more information, see Configuring NuGet behavior.

备注

在 1.x C# 函数中,NuGet 包是通过 project.json 文件而非 function.proj 文件引用的。In 1.x C# functions, NuGet packages are referenced with a project.json file instead of a function.proj file.

对于 1.x 函数,请改用 project.json 文件。For 1.x functions, use a project.json file instead. 下面是 project.json 文件示例:Here is an example project.json file:

{
  "frameworks": {
    "net46":{
      "dependencies": {
        "Microsoft.ProjectOxford.Face": "1.1.0"
      }
    }
   }
}

使用 function.proj 文件Using a function.proj file

  1. 在 Azure 门户中打开函数。Open the function in the Azure portal. 日志选项卡显示包安装输出。The logs tab displays the package installation output.
  2. 若要上传 function.proj 文件,请使用 Azure Functions 开发人员参考主题中如何更新函数应用文件部分描述的方法之一。To upload a function.proj file, use one of the methods described in the How to update function app files in the Azure Functions developer reference topic.
  3. 上传完 function.proj 文件后,将在函数的流日志中看到类似以下示例的输出:After the function.proj file is uploaded, you see output like the following example in your function's streaming log:
2018-12-14T22:00:48.658 [Information] Restoring packages.
2018-12-14T22:00:48.681 [Information] Starting packages restore
2018-12-14T22:00:57.064 [Information] Restoring packages for D:\local\Temp\9e814101-fe35-42aa-ada5-f8435253eb83\function.proj...
2016-04-04T19:02:50.511 Restoring packages for D:\home\site\wwwroot\HttpTriggerCSharp1\function.proj...
2018-12-14T22:01:00.844 [Information] Installing Newtonsoft.Json 10.0.2.
2018-12-14T22:01:01.041 [Information] Installing Microsoft.ProjectOxford.Common.DotNetStandard 1.0.0.
2018-12-14T22:01:01.140 [Information] Installing Microsoft.ProjectOxford.Face.DotNetStandard 1.0.0.
2018-12-14T22:01:09.799 [Information] Restore completed in 5.79 sec for D:\local\Temp\9e814101-fe35-42aa-ada5-f8435253eb83\function.proj.
2018-12-14T22:01:10.905 [Information] Packages restored.

环境变量Environment variables

若要获取环境变量或应用设置值,请使用 System.Environment.GetEnvironmentVariable,如以下代码示例所示:To get an environment variable or an app setting value, use System.Environment.GetEnvironmentVariable, as shown in the following code example:

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

在运行时绑定Binding at runtime

在 C# 和其他 .NET 语言中,可以使用命令性绑定模式,而不是 function.json 中的声明式绑定。In C# and other .NET languages, you can use an imperative binding pattern, as opposed to the declarative bindings in function.json. 当绑定参数需要在运行时(而非在设计时)计算时,命令性绑定很有用。Imperative binding is useful when binding parameters need to be computed at runtime rather than design time. 通过此模式,可以在函数代码中动态绑定到受支持的输入和输出绑定。With this pattern, you can bind to supported input and output bindings on-the-fly in your function code.

如下所示定义命令性绑定:Define an imperative binding as follows:

  • 对于所需的命令性绑定,不要包含 function.json 中的条目。Do not include an entry in function.json for your desired imperative bindings.
  • 传递输入参数 Binder binderIBinder binderPass in an input parameter Binder binder or IBinder binder.
  • 使用下面的 C# 模式执行数据绑定。Use the following C# pattern to perform the data binding.
using (var output = await binder.BindAsync<T>(new BindingTypeAttribute(...)))
{
    ...
}

BindingTypeAttribute 是定义了绑定的 .NET 属性,T 是该绑定类型所支持的输入或输出类型。BindingTypeAttribute is the .NET attribute that defines your binding and T is an input or output type that's supported by that binding type. T 不能是 out 参数类型(例如 out JObject)。T cannot be an out parameter type (such as out JObject). 例如, 移动应用表输出绑定支持6 种输出类型, 但只能使用<ICollector T >或。 IAsyncCollector<T> TFor example, the Mobile Apps table output binding supports six output types, but you can only use ICollector<T> or IAsyncCollector<T> for T.

单属性示例Single attribute example

下面的示例代码使用在运行时定义的 blob 路径创建存储 blob 输出绑定,然后将字符串写入此 blob。The following example code creates a Storage blob output binding with blob path that's defined at run time, then writes a string to the 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 是支持的输出绑定类型。BlobAttribute defines the Storage blob input or output binding, and TextWriter is a supported output binding type.

多属性示例Multiple attribute example

上一个示例获取函数应用的主存储帐户连接字符串(即 AzureWebJobsStorage)的应用设置。The preceding example gets the app setting for the function app's main Storage account connection string (which is AzureWebJobsStorage). 通过添加 StorageAccountAttribute 和将属性数组传入 BindAsync<T>(),可指定要用于存储帐户的自定义应用设置。You can specify a custom app setting to use for the Storage account by adding the StorageAccountAttribute and passing the attribute array into BindAsync<T>(). 使用一个 Binder 参数而非 IBinderUse a Binder parameter, not IBinder. 例如:For example:

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 属性及其定义所在的包。The following table lists the .NET attributes for each binding type and the packages in which they are defined.

绑定Binding 特性Attribute 添加引用Add reference
Cosmos DBCosmos DB Microsoft.Azure.WebJobs.DocumentDBAttribute #r "Microsoft.Azure.WebJobs.Extensions.CosmosDB"
事件中心Event Hubs Microsoft.Azure.WebJobs.ServiceBus.EventHubAttribute, Microsoft.Azure.WebJobs.ServiceBusAccountAttributeMicrosoft.Azure.WebJobs.ServiceBus.EventHubAttribute, Microsoft.Azure.WebJobs.ServiceBusAccountAttribute #r "Microsoft.Azure.Jobs.ServiceBus"
Mobile 应用Mobile Apps Microsoft.Azure.WebJobs.MobileTableAttribute #r "Microsoft.Azure.WebJobs.Extensions.MobileApps"
通知中心Notification Hubs Microsoft.Azure.WebJobs.NotificationHubAttribute #r "Microsoft.Azure.WebJobs.Extensions.NotificationHubs"
服务总线Service Bus Microsoft.Azure.WebJobs.ServiceBusAttribute, Microsoft.Azure.WebJobs.ServiceBusAccountAttributeMicrosoft.Azure.WebJobs.ServiceBusAttribute, Microsoft.Azure.WebJobs.ServiceBusAccountAttribute #r "Microsoft.Azure.WebJobs.ServiceBus"
存储队列Storage queue Microsoft.Azure.WebJobs.QueueAttribute, Microsoft.Azure.WebJobs.StorageAccountAttributeMicrosoft.Azure.WebJobs.QueueAttribute, Microsoft.Azure.WebJobs.StorageAccountAttribute
存储 blobStorage blob Microsoft.Azure.WebJobs.BlobAttribute, Microsoft.Azure.WebJobs.StorageAccountAttributeMicrosoft.Azure.WebJobs.BlobAttribute, Microsoft.Azure.WebJobs.StorageAccountAttribute
存储表Storage table Microsoft.Azure.WebJobs.TableAttribute, Microsoft.Azure.WebJobs.StorageAccountAttributeMicrosoft.Azure.WebJobs.TableAttribute, Microsoft.Azure.WebJobs.StorageAccountAttribute
TwilioTwilio Microsoft.Azure.WebJobs.TwilioSmsAttribute #r "Microsoft.Azure.WebJobs.Extensions.Twilio"

后续步骤Next steps