在本地使用 Visual Studio 创建和测试简单的 Azure Functions

已完成

可从 Azure 门户中编写、调试和部署 Azure 函数。 但是,直接在生产、过渡或测试环境中编写函数可能不适合。 例如,编写 Azure Functions 的自动单元测试,或者在 Azure 中对 Functions 应用使用 Azure Functions 的按需部署功能。 通常,开发人员更倾向于使用代码编辑器和开发工具,而不是 Azure 门户提供的环境。 通过使用 Visual Studio,你可在单个项目中使用其他代码和服务开发和管理 Azure Functions 代码。

在线上奢侈手表方案中,开发者已经熟悉 Visual Studio 2022。 因此,你决定使用 Visual Studio 作为创建 Azure Functions 的主要开发环境。 此外,在将函数部署到 Azure 之前,Visual Studio 为本地测试函数提供了绝佳环境。

在本单元,学习如何使用 Visual Studio 中提供的工具在本地计算机上生成和测试 Azure 函数。

重要

本文支持在进程内与运行时配合运行的 .NET 类库函数。 C# 函数还可以在进程外运行并与 Functions 运行时隔离。 独立工作进程模型是在当前版本的 Functions 运行时中运行非 LTS 版 .NET 和 .NET Framework 应用的唯一方法。 有关详细信息,请参阅 .NET 独立工作进程函数

修改 Visual Studio 安装

首先使用开发环境所需要的 Web 和云工具来设置 Visual Studio。

  1. 本地安装 Visual Studio 2022 后,打开“Visual Studio 安装程序”,然后在 Visual Studio Community 2022 上,选择“修改” 。

    Visual Studio 安装程序的屏幕截图,其中突出显示了“修改”。

  2. 随即出现“修改 - Visual Studio”页面。

    “修改 Visual Studio Community 2022 工作负载”选项卡的屏幕截图,其中突出显示了 ASP.NET 和 Web 开发及 Azure 开发。

  3. 在“工作负载”选项卡上,选中“ASP.NET 和 Web 开发”和“Azure 开发”复选框,然后选择“修改”。

  4. 在验证对话框中,选择“是”。 随机将显示“Visual Studio 安装程序”页,并显示正在安装的包的进度。

适用于 Visual Studio 的 Azure Functions 工具扩展

Azure Functions Tools 是一项 Visual Studio 扩展,用于在本地开发环境中创建、测试和部署 Azure Functions。 为了快速创建新的 Azure 函数应用,此扩展为你提供了一个模板,可用于生成函数,然后直接将该函数从 Visual Studio 部署到 Azure。

Visual Studio 2022 中随附 Azure Functions 和 Web 作业工具扩展。

Azure 函数应用

函数应用托管一个或多个函数。 它为函数代码提供了环境和运行时。

函数通过事件触发,而不是直接从应用中调用。 可指定会触发 Azure 函数应用中每个函数的事件类型。 可用事件包括:

  • Blob 触发器。 在 Azure Blob 存储中上传或修改文件时,会运行此函数类型。
  • 事件中心触发器。 事件中心收到消息时,事件中心触发器会运行函数。
  • Azure Cosmos DB 触发器。 当文档添加到 Azure Cosmos DB 数据库或在其中进行修改时,此触发器会运行。 可使用此触发器将 Azure Cosmos DB 与其他服务集成。 例如,如果将表示客户订单的文档添加到数据库,则可使用触发器将订单副本发送到队列进行处理。
  • Http 触发器。 当 Web 应用中发生 HTTP 请求时,HTTP 触发器会运行该函数。 还可使用此触发器响应 Webhook。 Webhook 是在修改网站托管的项时发生的回叫。 例如,可创建一个函数,当存储库中的项发生更改时,该函数将由 GitHub 存储库中的 Webhook 触发。
  • 队列触发器。 当新项添加到 Azure 存储队列时,此触发器将启动函数。
  • 服务总线队列触发器。 当新项添加到 Azure 服务总线队列时,此触发器将运行函数。
  • 服务总线主题触发器。 此触发器运行该函数以响应到达服务总线主题的新消息。
  • 计时器触发器。 此事件按照自定义的计划按一定的间隔时间运行函数。

显示可用的 Azure Functions 触发器的屏幕截图,其中突出显示了 HTTP 触发器。

下表显示了可与特定版本的 Functions 配合使用的 .NET Core 或 .NET Framework 的最高级别。

Functions 运行时版本 进程内 独立工作进程
Functions 4.x .NET 6.0 .NET 6.0
.NET 7.0
.NET 8.0
.NET Framework 4.8
Functions 1.x .NET Framework 4.8 不适用

Azure 函数应用在 Azure 存储中存储管理信息、代码和日志。 要保存此数据,需创建一个存储帐户。 存储帐户必须支持 Azure Blob、队列、文件和表存储;为此,请使用通用 Azure 存储帐户。 可使用前面显示的对话框指定要用于该函数的存储帐户。

函数可以执行特权或敏感操作。 可公开由 HTTP 请求触发的函数。 可能需要限制将此函数运行到所选用户组的能力。 可指定触发该函数所需的访问权限来保护函数。 由 HTTP 请求触发的函数支持三个级别的访问权限:

  • 匿名。 无需身份验证,任何用户都可以触发该函数。
  • 函数。 HTTP 请求必须提供一个密钥,使 Azure Functions 运行时能够授权请求。 可单独创建此密钥,也可使用 Azure 门户对其进行维护。
  • 管理员。类似于 Function。 用户必须使用触发该函数的 HTTP 请求指定密钥。 区别在于此密钥是管理员密钥。 此密钥可用于访问函数应用中的任何函数。 使用功能键,可单独创建此密钥。

如果正在创建由 HTTP 请求以外的事件触发的函数,则需要提供连接字符串以及函数应用访问触发事件的资源所需的其他详细信息。 例如,如果正在编写由 Blob 存储事件触发的函数,则必须为相应的 Blob 存储帐户指定连接字符串。

Azure Functions 的结构

Azure Functions 作为静态类实现。 此类提供名为 Run 的静态异步方法,可充当该类的入口点。

传递给 Run 方法的参数提供触发器的上下文。 如果是 HTTP 触发器,则该函数会收到一个 HttpRequest 对象。 此对象包含请求的标头和主体。 可使用任何 HTTP 应用中提供的相同技术访问请求中的数据。 应用于此函数的属性指定授权要求(在本例中为 Anonymous),以及函数响应的 HTTP 操作(GET 和 POST)。

以下由 Visual Studio 生成的代码示例检查作为请求 URL 一部分所提供的查询字符串,并查找名为 name 的参数。 该代码还使用 StreamReader 来反序列化请求的主体,并尝试从请求中读取名为 name 的属性的值。 如果在查询字符串或请求正文中找到了 name,则会在响应中返回 name 值。 否则,该函数会生成包含以下消息的错误响应:请在查询字符串或请求正文中传递名称

public static class Function1
{
    [FunctionName("Function1")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] 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;

        return name != null
            ? (ActionResult)new OkObjectResult($"Hello, {name}")
            : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
    }
}

该函数返回一个包含输出数据和结果的值,包装在 IActionResult 对象中。 该值将在请求的 HTTP 响应主体中返回。

不同类型的触发器接收不同的输入参数和返回类型。 下一个示例显示为 Blob 触发器生成的代码。 在此示例中,可以通过 Stream 对象返回 blob 的内容,还提供了 blob 的名称。 触发器不返回任何数据,其用途是读取和处理命名 blob 中的数据。

public static class Function2
{
    [FunctionName("Function2")]
    public static void Run([BlobTrigger("samples-workitems/{name}", Connection = "xxxxxxxxxxxxxxxxxxxxxxx")]Stream myBlob, string name, ILogger log)
    {
        log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
    }
}

在所有情况下,函数都会传递 ILogger 参数。 该函数可以使用此参数来编写日志消息,函数应用会写入该消息以供稍后分析。

函数还包含指定触发器类型的元数据、安全要求以及任何其他特定信息。 可使用 HttpTrigger、BlobTrigger 或其他触发器属性修改元数据,如示例中所示。 函数前面的 FunctionName 属性是函数应用使用的函数的标识符。 此名称不必与函数名称相同,但最好保持它们同步以避免混淆。

在本地测试 Azure 函数应用

可使用 Visual Debugger 在本地生成和测试 Azure 函数应用。 要启动调试程序,请按 F5 或选择“调试”菜单上的“开始调试”。 函数运行时的本地版本启动。 你的函数可用于测试。 该示例显示了运行时托管 Function1,这是由 HTTP 事件触发的函数。 URL 指示该函数当前附加到的终结点。

显示 Azure 函数运行时 - 示例 1 的屏幕截图。

如果打开 Web 浏览器并访问此 URL,则会触发该函数。 下图显示了不包含主体的 HTTP GET 请求生成的响应。 可看到从函数返回 BadRequestObjectResult 对象的代码生成的消息。

显示 Azure 函数运行时的屏幕截图。

如果提供包含 name 参数的查询字符串,则该函数会读取并处理此值

显示 Azure 函数运行时 - 示例 2 的屏幕截图。

代码运行时,你会看到函数运行时窗口中出现跟踪消息。 如果需要设置断点并检查函数中的控制流,则可以在 Visual Studio 中使用标准调试功能。