使用 Azure Functions 和 API 管理整合在 Visual Studio 中建立無伺服器 API

REST API 通常會使用 OpenAPI 定義來描述。 此定義包含有關 API 中的作業,以及應如何為 API 建構要求和回應資料的資訊。

在本教學課程中,您會了解如何:

  • 在 Visual Studio 中建立無伺服器函式專案
  • 使用內建 OpenAPI 功能在本機測試函式 API
  • 透過 API 管理整合將專案發佈至 Azure 中的函式應用程式
  • 取得函式的存取金鑰並在 API 管理中加以設定
  • 下載 OpenAPI 定義檔案

您所建立的無伺服器函式提供 API,可讓您判斷風力發電機的緊急修復是否符合成本效益。 由於您建立的函式應用程式與 API 管理執行個體都會使用取用方案,因此完成本教學課程的成本最低。

注意

本文中精選的 OpenAPI 和 API 管理整合目前僅針對同處理序 C# 類別庫函式受到支援。 隔離的背景工作處理序 C# 類庫函數和所有其他語言執行階段應該改為利用源自入口網站的 Azure API 管理整合。

必要條件

建立 Functions 專案

Visual Studio 中的 Azure Functions 專案範本會建立可發行至 Azure 中函式應用程式的專案。 您也會建立 HTTP 觸發的函式以支援 OpenAPI 定義檔案 (先前稱為 Swagger 檔案) 產生。

  1. 在 Visual Studio 功能表中,選取 [檔案]> [新增]> [專案]

  2. 在 [建立新專案] 的搜尋方塊中輸入函式,選擇 [Azure Functions] 範本,然後選取 [下一步]

  3. 在 [設定您的新專案] 中,輸入專案的 [專案名稱] (像是 TurbineRepair),然後選取 [建立]

  4. 針對 [建立新的 Azure Functions 應用程式] 設定,請使用下表中的值:

    設定 Description
    函式背景工作 .NET 6 此值會建立一個在 Azure Functions 執行階段 4.x 版上同處理序執行的函式專案,這是產生 OpenAPI 檔案所必需的。
    函式範本 使用 OpenAPI 的 HTTP 觸發程序 此值會建立 HTTP 要求所觸發的函式,並能夠產生 OpenAPI 定義檔案。
    將 Azurite 用於執行階段儲存體帳戶 (AzureWebJobsStorage) Selected 您可以使用模擬器進行 HTTP 觸發程序函式的本機開發。 因為 Azure 中的函數應用程式需要儲存體帳戶,所以當您將專案發佈至 Azure 時,就會指派或建立一個儲存體帳戶。
    授權等級 Function 在 Azure 中執行時,用戶端必須在存取端點時提供金鑰。 如需金鑰和授權的詳細資訊,請參閱函式存取金鑰

    Azure Functions project settings

  5. 選取 [建立],以透過 OpenAPI 支援建立函式專案和 HTTP 觸發程序函式。

Visual Studio 會建立一個專案和名為 Function1 的類別,其中包含 HTTP 觸發程序函式類型的重複使用程式碼。 接下來,您會以自己的自訂程式碼取代此函式範本程式碼。

更新函式程式碼

此函式會使用採用兩個參數的 HTTP 觸發程序:

參數名稱 描述
hours 進行渦輪機修復的估計時間,最多到最接近的整個小時。
capacity 渦輪機的容量 (以千瓦為單位)。

然後,此函式會計算修復的費用,以及渦輪機在 24 小時內的收入。 參數是在查詢字串或 POST 要求的承載中提供。

在 Function1.cs 專案檔中,以下列程式碼取代所產生的類別庫程式碼內容:

using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;

namespace TurbineRepair
{
    public static class Turbines
    {
        const double revenuePerkW = 0.12;
        const double technicianCost = 250;
        const double turbineCost = 100;

        [FunctionName("TurbineRepair")]
        [OpenApiOperation(operationId: "Run")]
        [OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
        [OpenApiRequestBody("application/json", typeof(RequestBodyModel), 
            Description = "JSON request body containing { hours, capacity}")]
        [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(string),
            Description = "The OK response message containing a JSON result.")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            // Get request body data.
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            int? capacity = data?.capacity;
            int? hours = data?.hours;

            // Return bad request if capacity or hours are not passed in
            if (capacity == null || hours == null)
            {
                return new BadRequestObjectResult("Please pass capacity and hours in the request body");
            }
            // Formulas to calculate revenue and cost
            double? revenueOpportunity = capacity * revenuePerkW * 24;
            double? costToFix = (hours * technicianCost) + turbineCost;
            string repairTurbine;

            if (revenueOpportunity > costToFix)
            {
                repairTurbine = "Yes";
            }
            else
            {
                repairTurbine = "No";
            };

            return (ActionResult)new OkObjectResult(new
            {
                message = repairTurbine,
                revenueOpportunity = "$" + revenueOpportunity,
                costToFix = "$" + costToFix
            });
        }
    }
    public class RequestBodyModel
    {
        public int Hours { get; set; }
        public int Capacity { get; set; } 
    }
}

此函式程式碼會傳回 YesNo 的訊息,指出緊急修復是否符合成本效益。 此外也會傳回渦輪機所代表的收益機會,與修復渦輪機的成本。

在本機執行並驗證 API

當您執行函式時,OpenAPI 端點可讓您輕鬆地使用所產生的頁面在本機試用函式。 您不需要在本機執行時提供函式存取金鑰。

  1. 按 F5 開始專案。 當 Functions 執行階段在本機開始時,輸出中會顯示一組 OpenAPI 和 Swagger 端點,以及函式端點。

  2. 在您的瀏覽器中,開啟 RenderSwaggerUI 端點,其看起來應該像 http://localhost:7071/api/swagger/ui。 頁面會根據您的 OpenAPI 定義進行轉譯。

  3. 選取 [POST]>[立即試用],輸入 hourscapacity的值作為查詢參數,或在 JSON 要求本文中輸入值,然後選取 [執行]

    Swagger UI for testing the TurbineRepair API

  4. 當您針對 hours 輸入 6 之類的整數值和針對 capacity 輸入 2500 之類的值時,您會收到類似下列範例的 JSON 回應:

    Response JSON data from the TurbineRepair function.

現在,您有一個函式,可判斷緊急修復是否符合成本效益。 接下來,您會將專案和 API 定義發佈至 Azure。

將專案發佈至 Azure

您的 Azure 訂用帳戶中必須具有函式應用程式,才可以發佈您的專案。 Visual Studio 發佈會在您第一次發佈專案時,建立函式應用程式。 其也可以建立與函式應用程式整合的 API 管理執行個體,以公開 TurbineRepair API。

  1. 在 [方案總管] 中,以滑鼠右鍵按一下專案,選取 [發佈],接著在 [目標] 中選取 [Azure],然後選取 [下一步]

  2. 針對 [特定目標],選擇 [Azure 函式應用程式 (Windows)],以建立在 Windows 上執行的函式應用程式,然後選取 [下一步]

  3. 在 [函式執行個體] 中,選擇 [建立新的 Azure 函式...]

    Create a new function app instance

  4. 使用下表中的指定值建立新的執行個體:

    設定 描述
    名稱 全域唯一的名稱 用以唯一識別新函式應用程式的名稱。 接受此名稱或輸入新的名稱。 有效字元:a-z0-9-
    訂用帳戶 您的訂用帳戶 要使用的 Azure 訂用帳戶。 接受此訂用帳戶,或從下拉式清單中選取一個新的訂用帳戶。
    資源群組 資源群組的名稱 要在其中建立函式應用程式的資源群組。 從下拉式清單中選取現有的資源群組,或選擇 [新增] 來建立新的資源群組。
    方案類型 耗用 當您將專案發佈至在取用方案中執行的函式應用程式時,您只需支付您的函式應用程式執行費用。 其他主控方案會產生較高的成本。
    地點 服務的位置 區域中選擇 位置,此位置應靠近您或靠近函式會存取的其他服務。
    Azure 儲存體 一般用途的儲存體帳戶 Functions 執行階段需要 Azure 儲存體帳戶。 選取 [新增] 以設定一般用途的儲存體帳戶。 您也可以選擇符合儲存體帳戶需求的現有帳戶。

    Create a new function app in Azure with Storage

  5. 選取 [建立],以在 Azure 中建立函數應用程式及其相關資源。 資源的建立狀態會顯示在視窗左下方。

  6. 回到 [函式執行個體],確定已勾選 [從套件檔案執行]。 您的函式應用程式會使用已啟用從套件執行模式的 Zip 部署來部署。 這是函式專案的建議部署方法,因為其可提高效能。

  7. 選取 [下一步],然後在 [API 管理] 頁面中,也要選擇 [+ 建立 API 管理 API]

  8. 使用下表中的值,在 API 管理中建立 API

    設定 Description
    API 名稱 TurbineRepair API 的名稱。
    訂用帳戶名稱 您的訂用帳戶 要使用的 Azure 訂用帳戶。 接受此訂用帳戶,或從下拉式清單中選取一個新的訂用帳戶。
    資源群組 資源群組的名稱 從下拉式清單中選取與函式應用程式相同的資源群組。
    API 管理服務 新增執行個體 選取 [新增] 以在無伺服器層中建立新的 API 管理執行個體。

    Create API Management instance with API

  9. 選取 [建立] 以從函式整合透過 TurbineRepair API 建立 API 管理執行個體。

  10. 選取 [完成],確認 [發佈] 頁面顯示 [已可發行],然後選取 [發佈],將包含專案檔的套件部署到 Azure 中的新函數應用程式。

    部署完成之後,[發佈] 索引標籤中會顯示 Azure 中函式應用程式的根 URL。

取得函式存取金鑰

  1. 在 [發佈] 索引標籤中,選取 [裝載] 旁的省略符號 (...),然後選取 [在 Azure 入口網站中開啟]。 您建立的函式應用程式會在預設瀏覽器的 Azure 入口網站中開啟。

  2. 在 [函式] 底下,選取 [函式]>[TurbineRepair],然後選取 [函式金鑰]

    Get an access key for the TurbineRepair function

  3. 在 [函式金鑰] 底下,選取 [預設值],然後複製此。 您現在可以在 API 管理中設定此金鑰,以便存取函式端點。

設定 API 管理

  1. 在 [發佈] 索引標籤中,選取 [裝載] 旁的省略符號 (...),然後選取 [在 Azure 入口網站中開啟 API]。 您建立的 API 管理執行個體會在預設瀏覽器中的 Azure 入口網站中開啟。 此 API 管理執行個體已經連結至您的函式應用程式。

  2. 在 [API] 底下,選取 [Azure Functions 上的 OpenAPI 文件]>[POST 執行],然後在 [輸入處理] 底下選取 [新增原則]

    Add an inbound policy to the API

  3. 在 [新增處理] 下方的 [設定查詢參數] 中,針對 [名稱] 輸入 code,選取 [+值],貼上所複製的函式金鑰,然後選取 [儲存]。 API 管理會在將呼叫傳遞至函式端點時包含函式金鑰。

    Provide Function credentials to the API inbound processing rule

現在已設定函式金鑰,您可以呼叫 API,以確認其可在 Azure 中裝載時運作。

確認 Azure 中的 API

  1. 在 API 中,選取 [測試] 索引標籤,然後選取 [POST 執行],在 [要求本文]>[未經處理] 中輸入下列程式碼,然後選取 [傳送]

    {
        "hours": "6",
        "capacity": "2500"
    }
    

    OpenAPI test page in the API Management API

    如同以往,您也可以提供與查詢參數相同的值。

  2. 選取 [傳送],然後檢視 HTTP 回應,以確認從 API 傳回相同的結果。

下載 OpenAPI 定義

如果您的 API 可以正常運作,就可以下載 OpenAPI 定義。

    1. 在 [API] 底下,選取 [Azure Functions 上的 OpenAPI 文件]、選取省略符號 (...),然後選取 [匯出]

    Download OpenAPI definition

  1. 選擇 API 匯出的方法,包括各種格式的 OpenAPI 檔案。 您也可以將 API 從 Azure API 管理匯出至 Power Platform

清除資源

在上述步驟中,您已建立資源群組中的 Azure 資源。 如果您預期未來不需要這些資源,則可以藉由刪除資源群組予以刪除。

從 Azure 入口網站功能表或 [首頁] 頁面,選取 [資源群組]。 然後,在 [資源群組] 頁面上,選取您建立的群組。

在 [myResourceGroup] 頁面上,確定所列出的資源是您想要刪除的項目。

選取 [刪除資源群組],在文字方塊中輸入您的群組名稱以便確認,然後選取 [刪除]

下一步

您已使用 Visual Studio 2022 來建立自我記錄的函式,因為 OpenAPI 延伸模組與 API 管理整合。 現在可以在入口網站的 API 管理中精修定義。 您也可以深入了解 API 管理