练习 - 使用 Visual Studio 在本地创建和测试 Azure 函数

已完成

Visual Studio 为创建和测试 Azure 函数应用提供了一个绝佳环境。 在将 Azure Functions 部署到云之前,可在本地开发 Azure Functions 并验证其是否正常运行。

在奢侈手表在线网站场景中,函数的要求为:当给定手表的型号时,该函数返回有关手表的详细信息。 需要返回的数据包括制造商、表壳背面类型(实心、透明或雕刻)、外圈、表盘样式、表壳表面处理、珠宝数量等信息。

在本练习中,你将使用 Visual Studio 对此函数的一个版本进行本地实现和测试。

注意

在开始本练习之前,请确保已安装 Visual Studio 2022,以及 Web 和云工作负载扩展 ASP.NET 和 Web 开发和Azure 开发

创建 Azure 函数应用

使用 Azure Functions 模板创建 Azure 函数应用。

  1. 启动“Visual Studio 安装程序”并在“Visual Studio 2022”开始页上,选择“修改” 。

  2. 请确保选择“ASP.NET 和 Web 开发”以及“Azure 开发”且均可用,(如果不选择“下载时安装”),然后选择“关闭”。

    突出显示了 asp dot net 和 Azure 开发工作负载的 Visual Studio 2022 的屏幕截图。

  3. 在“Visual Studio 2022”开始页上,选择“启动”。

  4. 在“开始”菜单上,选择“新建项目”。 随即显示“创建新项目”页。

  5. 搜索或滚动到“Azure Functions”模板,然后选择“下一步”。

    Visual Studio 2022 的屏幕截图:“新建项目”页面,其中突出显示了 Azure Functions 模板。

  6. 随即显示“配置新项目”页。 输入以下值。

    字段
    项目名称 WatchPortalFunction
    位置 通过浏览到文件夹或在本地计算机上创建文件夹,选择要存储项目的位置。
    解决方案名称 接受“WatchPortalFunction”(默认)。
    将解决方案和项目放在同一目录中 未勾选(未选择)。 此设置将确保此模块的文件夹结构正确。

    “配置新项目”页面的屏幕截图,其中突出显示了“新建”。

  7. 选择“下一页”。

  8. “其他信息”页面出现。

  9. 选择以下值。

    字段
    Dotnet 版本 *.NET 6.0(长期支持)
    函数触发器 Http 触发器
    将 Azurite 用作运行时存储账户 (AzureWebJobsStorage) 选中
    启用 Docker 未选中
    授权级别 匿名

    如果 Visual Studio 通知显示更新已准备就绪,选择“刷新”。

  10. 选择“创建” 。

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

    Visual Studio 创建 WatchPortalFunction 项目,并显示代码编辑器窗口中的 Functions 应用源代码文件 Function1.cs。 该文件包含名为 Function1 的类的代码。

    如下面的示例代码所示,Function1 类包含 HTTP 触发器模板中的样板代码。 Run 方法使用 [FunctionName ("Function1")] 属性进行批注。 在上一单元中,我们了解到 Run 方法的样板参数是一个 HttpRequest 对象,其中包含触发函数的请求的详细信息,以及用于记录跟踪信息的跟踪日志条目。

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

创建 WatchInfo Azure Function

  1. 在“视图”菜单中,选择“解决方案资源管理器”。 在“解决方案资源管理器”窗口中,右键单击“WatchPortalFunction”Azure Functions 项目,接着在上下文菜单中选择“添加”“新建 Azure 函数”。

    “解决方案资源管理器”窗口的屏幕截图。用户选择了“添加”->“新建 Azure 函数”。

  2. 在“添加新项 - WatchPortalFunction”窗口中,选择“Azure Functions”。 在“名称”字段中,输入“WatchInfo.cs”,然后选择“添加”。

    “添加新项”窗口的屏幕截图。选择 Azure Function 模板,并将新函数命名为WatchInfo.cs。

  3. 在“新建 Azure 函数 - WatchInfo”窗口中,选择“Http 触发器”。 在“授权级别”下拉列表中,选择“匿名”,然后选择“添加”。

    “新建 Azure 函数”窗口的屏幕截图。已选择具有匿名访问权限的 Http 触发器。

    Visual Studio 会创建一个新函数,并使用 Run 属性对 [FunctionName("WatchInfo")] 方法进行批注。

  4. Run 函数的正文中,删除 log.LogInformation 行后的代码。 结果应如下所示。

    namespace WatchPortalFunction
    {
        public static class WatchInfo
        {
            [FunctionName("WatchInfo")]
            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.");
            }
        }
    }
    
  5. 将以下代码插入 Run 行后的 log.LogInformation 方法的正文中。

    // Retrieve the model id from the query string
    string model = req.Query["model"];
    
    // If the user specified a model id, find the details of the model of watch
    if (model != null)
    {
        // Use dummy data for this example
        dynamic watchinfo = new { Manufacturer = "abc", CaseType = "Solid", Bezel = "Titanium", Dial = "Roman", CaseFinish = "Silver", Jewels = 15 };
    
        return (ActionResult)new OkObjectResult($"Watch Details: {watchinfo.Manufacturer}, {watchinfo.CaseType}, {watchinfo.Bezel}, {watchinfo.Dial}, {watchinfo.CaseFinish}, {watchinfo.Jewels}");
    }
    return new BadRequestObjectResult("Please provide a watch model in the query string");
    

    此代码从 HTTP 请求中的查询字符串中读取 model 参数,并返回该监视模型的详细信息。 在此示例代码中,我们创建了无论 watchinfo 值如何都会返回的虚拟 model 数据。 此函数返回包含这些详细信息的响应。 或者,如果 HTTP 请求不包含查询字符串,该函数将返回错误消息。 在实际示例中,你会使用 model 值来查找并返回正确的 watchinfo

在本地测试 Azure Function

  1. 在命令栏上,选择“调试”“开始调试”。

    Visual Studio 生成 Azure 函数应用并启动 Azure Functions 运行时。 运行时启动时,将打开“输出”窗口以显示消息。 运行时准备就绪后,将显示一个 HTTP 函数列表以及可用于触发每个函数的 URL。

    Azure Functions 运行时窗口的屏幕截图。运行时启动 Azure Function 应用,并显示 Function1 和 WatchInfo Azure Functions 的 URL。

  2. 打开 Web 浏览器,并输入运行时窗口中显示的 URL 默认 URL 是 http://localhost:7071/api/WatchInfo?model=abc,因此,这就是我们在本练习中所使用的 URL。 此请求触发 WatchInfo 函数,并将模型 abc 作为查询字符串参数传递。 Web 浏览器应显示函数生成的虚拟详细信息。

    触发 WatchInfo Azure Functions 的 Web 浏览器的屏幕截图。该函数返回所提供的 URL 查询字符串中指定模型的虚拟详细信息。

  3. 输入 URL http://localhost:7071/api/WatchInfo。 此请求不包含查询字符串。 触发器返回错误响应,Web 浏览器显示 Please provide a watch model in the query string 消息。

  4. 关闭 Web 浏览器,但保持 Azure 函数应用正常运行。

  5. 在 Visual Studio 中,在从查询字符串检索模型的代码行上设置断点。

    显示从查询字符串中读取模型的语句上的断点的 Visual Studio 屏幕截图。

  6. 重启 Web 浏览器,然后输入不带查询字符串的 URL http://localhost:7071/api/WatchInfo

    Visual Studio 在暂停执行的断点处突出显示代码。

  7. 在 Visual Studio 中,按 F10 跳过断点处的语句。

  8. 在“调试器”窗口的“Autos”选项卡中,验证 变量是否为 。 该变量显示此值,因为查询字符串不包含模型参数。

    显示模型变量值的 Visual Studio 调试器屏幕截图。

  9. 再次按 F10,并验证控件是否跳转到返回 BadRequestObjectResult 对象的语句。

  10. F5 继续运行该方法并返回到 Web 浏览器。 应显示相同的错误消息。

  11. 在 Web 浏览器中,输入带有查询字符串和模型参数的 URL。 在调试器中单步调试函数,并验证是否正确检索了模型。 应使用参数的值填充 model 变量,并将模型的详细信息作为 OkObjectResult 对象返回。

  12. 在菜单栏上,选择“调试”“停止调试”>

在本练习中,你已了解如何在 Visual Studio 中使用 Azure Functions 工具扩展简化 Azure Function 应用的创建体验,后者可让你使用熟悉的工具来生成和调试代码。