使用 Visual Studio 來開發 Azure Functions

Visual Studio 可讓您開發、測試和部署 C# 類別庫函式至 Azure。 如果這是您第一次體驗 Azure Functions,請參閱 Azure Functions 簡介

若要快速入門,先考慮完成適用於 Visual Studio 的 Functions 快速入門

本文提供如何使用 Visual Studio 來開發 C# 類別庫函式並將其發佈至 Azure 的詳細資料。 開發 C# 類別庫函式有兩種模型:隔離式背景工作角色模型同處理序模型

您正在閱讀隔離式背景工作角色模型版本這篇文章。 您可以在文章頂端選擇慣用模型。

您正在閱讀同處理序模型版本這篇文章。 您可以在文章頂端選擇慣用模型。

除非另有註明,否則顯示的程式和範例適用於 Visual Studio 2022。 如需 Visual Studio 2022 版本的詳細資訊,請參閱版本資訊預覽版版本資訊

必要條件

  • Visual Studio 2022,包括 Azure 開發工作負載。

  • 發佈程序期間,系統會在您的訂用帳戶中建立您需要的其他資源,例如 Azure 儲存體帳戶。

  • 如果您沒有 Azure 訂用帳戶,請在開始之前先建立 Azure 免費帳戶

建立 Azure Functions 專案

Visual Studio 中的 Azure Functions 專案範本會建立可發行至 Azure 中函數應用程式的 C# 類別庫專案。 您可以使用函式應用程式將多個函式群組為邏輯單位,以方便管理、部署、調整和共用資源。

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

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

  3. 在 [設定您的新專案] 中,輸入專案的專案名稱,然後選取 [建立]。 函式應用程式名稱必須是有效的 C# 命名空間,因此不會使用底線、連字號或任何其他非英數字元。

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

    設定 Description
    .NET 版本 .NET 6 已隔離 此值會建立在隔離式背景工作處理序中執行的函式專案。 隔離式背景工作處理序支援其他非 LTS 版本的 .NET 和 .NET Framework。 如需詳細資訊,請參閱 Azure Functions 執行階段版本概觀
    函式範本 HTTP 觸發程序 此值會建立 HTTP 要求所觸發的函式。
    儲存體帳戶 (AzureWebJobsStorage) 儲存體模擬器 因為 Azure 中的函數應用程式需要儲存體帳戶,所以當您將專案發佈至 Azure 時,就會指派或建立一個儲存體帳戶。 HTTP 觸發程式不會使用 Azure 儲存體帳戶連接字串;所有其他觸發程式類型都需要有效的 Azure 儲存體帳戶連接字串。
    授權等級 匿名 建立的函式可以由任何用戶端觸發,而不需提供金鑰。 此授權設定可以讓測試新函式變得簡單。 如需金鑰和授權的詳細資訊,請參閱 授權金鑰HTTP 和 Webhook 繫結

    Screenshot of Azure Functions project settings

    設定 Description
    .NET 版本 .NET 6 此值會建立一個函數專案,執行 Azure Functions 執行階段版本 4.x 的內含式。 如需詳細資訊,請參閱 Azure Functions 執行階段版本概觀
    函式範本 HTTP 觸發程序 此值會建立 HTTP 要求所觸發的函式。
    儲存體帳戶 (AzureWebJobsStorage) 儲存體模擬器 因為 Azure 中的函數應用程式需要儲存體帳戶,所以當您將專案發佈至 Azure 時,就會指派或建立一個儲存體帳戶。 HTTP 觸發程式不會使用 Azure 儲存體帳戶連接字串;所有其他觸發程式類型都需要有效的 Azure 儲存體帳戶連接字串。
    授權等級 匿名 建立的函式可以由任何用戶端觸發,而不需提供金鑰。 此授權設定可以讓測試新函式變得簡單。 如需金鑰和授權的詳細資訊,請參閱 授權金鑰HTTP 和 Webhook 繫結

    Screenshot of Azure Functions project settings

    請確定您已將 [授權層級] 設定為 [匿名]。 如果您選擇函式的預設層級,必須在要求中提供函式金鑰以存取您的函式端點。

  5. 選取 [建立] 以建立函式專案和 HTTP 觸發程序函數。

建立 Azure Functions 專案之後,專案範本會建立 C# 專案、安裝 Microsoft.Azure.Functions.WorkerMicrosoft.Azure.Functions.Worker.Sdk NuGet 套件,並設定目標 Framework。

建立 Azure Functions 專案之後,專案範本會建立 C# 專案、安裝 Microsoft.NET.Sdk.Functions NuGet 套件,並設定目標框架。

新專案含有下列檔案:

  • host.json:讓您設定 Functions 主機。 這些設定同時適用於在本機執行及在 Azure 中執行。 如需詳細資訊,請參閱 host.json 參考

  • local.settings.json:維持在本機執行函數時所使用的設定。 在 Azure 中執行時,不會使用這些設定。 如需詳細資訊,請參閱本機設定檔

    重要

    由於 local.settings.json 檔案可以包含祕密,因此,您必須從專案原始檔控制中排除它。 請確定此檔案的 [複製到輸出目錄] 設定為 [有更新時才複製]

如需詳細資訊,請參閱隔離式背景工作角色指南中的專案結構

如需詳細資訊,請參閱 Functions 類別庫專案

在本機使用應用程式設定

在 Azure 中的函數應用程式中執行時,函式所需的設定安全地儲存在應用程式設定中。 在本機開發期間,這些設定會改為新增至 local.settings.json 檔案中的 Values 集合。 local.settings.json 檔案也儲存本機開發工具使用的設定。

專案 local.settings.json 檔案中 Values 集合中的項目,是用來反映在 Azure 中鏡像函數應用程式應用程式設定中的項目。

當您發佈專案時,Visual Studio 不會自動上傳 local.settings.json 中的設定。 若要確定這些設定也存在於 Azure 中的函式應用程式,請在發佈專案之後上傳這些設定。 如需詳細資訊,請參閱函式應用程式設定ConnectionStrings 集合中的值永遠不會發佈。

您的程式碼也可以將這些函數應用程式設定值讀取為環境變數。 如需詳細資訊,請參閱環境變數

設定專案以進行本機開發

函數執行階段會在內部使用 Azure 儲存體帳戶。 針對 HTTP 和 Webhook 以外的所有觸發程序類型,將 Values.AzureWebJobsStorage 機碼設定為有效的 Azure 儲存體帳戶連接字串。 函數應用程式也可以針對專案所需的 AzureWebJobsStorage 連線設定,使用 Azure 模擬器。 若要使用模擬器,將 AzureWebJobsStorage 的值設定為 UseDevelopmentStorage=true。 請在部署前將此設定變更為實際的儲存體帳戶連線字串。 如需詳細資訊,請參閱本機儲存體模擬器

設定儲存體帳戶連接字串:

  1. 在 Azure 入口網站中,瀏覽至您的儲存體帳戶。

  2. 在 [存取金鑰] 索引標籤的 [安全性 + 網路] 下方,複製 key1連接字串

  3. 在您的專案中,開啟 local.settings.json 檔案並將 AzureWebJobsStorage 機碼的值設定為您所複製的連接字串。

  4. 重複上一步,針對函數所需的其他任何連接,將唯一機碼新增至 Values 陣列。

將函式新增至您的專案

在 C# 類別庫函式中,函式所使用的繫結是透過在程式碼中套用屬性來定義的。 當您從提供的範本建立函數觸發程序時,系統會為您套用這些觸發程序屬性。

  1. 在 [方案總管] 中,於專案節點按一下滑鼠右鍵,然後選取 [新增]> [新增 Azure Function]

  2. 輸入類別的 [名稱],然後選取 [新增]

  3. 選擇觸發程序,設定所需的繫結屬性,然後選取 [新增]。 下列範例顯示建立佇列儲存體觸發程序函數的設定。

    Create a Queue storage trigger function

    針對 Azure 儲存體服務觸發程序,勾選 [設定連線] 方塊,系統便會提示您選擇使用 Azurite 儲存體模擬器或參考佈建的 Azure 儲存體帳戶。 選取 [下一步],如果您選擇儲存體帳戶,Visual Studio 會嘗試連線到 Azure 帳戶並取得連接字串。 選擇 [在本機使用者祕密檔案中儲存連接字串值],然後選擇 [完成] 以建立觸發程序類別。

    此觸發程序範例會針對儲存體連線,透過名為 QueueStorage 的金鑰使用應用程式設定。 此金鑰 (儲存在 local.settings.json 檔案中) 會參考 Azure 模擬器或 Azure 儲存體帳戶。

  4. 檢查新加入的類別。 例如,下列 C# 類別代表基本佇列儲存體觸發程序函數:

    您會看到屬性為 Function 的靜態 Run() 方法。 這個屬性指出該方法是函數的進入點。

    using System;
    using Azure.Storage.Queues.Models;
    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.Logging;
    
    namespace Company.Function
    {
        public class QueueTriggerCSharp
        {
            private readonly ILogger<QueueTriggerCSharp> _logger;
    
            public QueueTriggerCSharp(ILogger<QueueTriggerCSharp> logger)
            {
                _logger = logger;
            }
    
            [Function(nameof(QueueTriggerCSharp))]
            public void Run([QueueTrigger("PathValue", Connection = "ConnectionValue")] QueueMessage message)
            {
                _logger.LogInformation($"C# Queue trigger function processed: {message.MessageText}");
            }
        }
    }
    

    您會看到屬性為 FunctionName 的靜態 Run() 方法。 這個屬性指出該方法是函數的進入點。

    using System;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Host;
    using Microsoft.Extensions.Logging;
    
    namespace Company.Function
    {
        public class QueueTriggerCSharp
        {
            [FunctionName("QueueTriggerCSharp")]
            public void Run([QueueTrigger("PathValue", Connection = "ConnectionValue")]string myQueueItem, ILogger log)
            {
                log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
            }
        }
    }
    

會將繫結特定屬性套用至提供給進入點方法的每個繫結參數。 屬性會將繫結資訊作為參數使用。 在上述範例中,第一個參數套用了 QueueTrigger 屬性,並指出佇列儲存體觸發程序函數。 佇列名稱和連接字串設定名稱會作為參數傳遞至 QueueTrigger 屬性。 如需詳細資訊,請參閱 Azure Functions 的 Azure 佇列儲存體繫結

請使用上述程序,對函式應用程式專案新增更多函式。 專案中的每個函數都可以有不同的觸發程序,但函數只能有一個觸發程序。 如需詳細資訊,請參閱 Azure Functions 觸發程序和繫結概念

新增繫結

和觸發程序一樣,輸入和輸出繫結會新增至函式作為繫結屬性。 請將繫結新增至函式,如下所示:

  1. 確定您設定的是用於本機開發的專案

  2. 在繫結的參考文章中尋找繫結特定 NuGet 套件需求,以此為特定繫結新增適當的 NuGet 延伸模組套件。 例如,您可以在事件中樞繫結參考文章中尋找事件中樞觸發程序的套件需求。

  3. 在套件管理員主控台中使用下列命令來安裝特定套件:

    Install-Package Microsoft.Azure.Functions.Worker.Extensions.<BINDING_TYPE> -Version <TARGET_VERSION>
    
    Install-Package Microsoft.Azure.WebJobs.Extensions.<BINDING_TYPE> -Version <TARGET_VERSION>
    

    在此範例中,將 <BINDING_TYPE> 取代為繫結延伸模組的特定名稱,並以套件的特定版本 (例如 4.0.0) 來取代 <TARGET_VERSION>。 有效的版本會列在 NuGet.org 的個別套件頁面上。

  4. 如果有繫結所需的應用程式設定,請將其新增至本機設定檔案中的 Values 集合。

    函式在本機執行時會使用這些值。 當函式在 Azure 中的函式應用程式中執行時,其會使用函式應用程式設定。 Visual Studio 可讓您輕鬆地將本機設定發佈至 Azure

  5. 在方法簽章中新增適當的繫結屬性。 在下列範例中,佇列訊息會觸發函式,而且輸出繫結會在不同的佇列中,使用相同文字建立新的佇列訊息。

     public class QueueTrigger
    {
        private readonly ILogger _logger;
    
        public QueueTrigger(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<QueueTrigger>();
        }
    
        [Function("CopyQueueMessage")]
        [QueueOutput("myqueue-items-destination", Connection = "QueueStorage")]
        public string Run([QueueTrigger("myqueue-items-source", Connection = "QueueStorage")] string myQueueItem)
        {
            _logger.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
            return myQueueItem;
        }
    }
    

    QueueOutput 屬性會定義方法上的繫結。 針對多個輸出繫結,您會改為將這個屬性放在傳回物件的字串屬性上。 如需詳細資訊,請參閱多重輸出繫結

    public static class SimpleExampleWithOutput
    {
        [FunctionName("CopyQueueMessage")]
        public static void Run(
            [QueueTrigger("myqueue-items-source", Connection = "QueueStorage")] string myQueueItem, 
            [Queue("myqueue-items-destination", Connection = "QueueStorage")] out string myQueueItemCopy,
            ILogger log)
        {
            log.LogInformation($"CopyQueueMessage function processed: {myQueueItem}");
            myQueueItemCopy = myQueueItem;
        }
    }
    

    out 參數上的 Queue 屬性會定義輸出繫結。

    佇列儲存體的連接是從 QueueStorage 設定中取得的。 如需詳細資訊,請參閱特定繫結的參考文章。

針對 Functions 支援的繫結如需完整清單,請參閱支援的繫結

在本機執行函式

Azure Functions Core Tools 可讓您在本機開發電腦上執行 Azure Functions 專案。 當您按 F5 對 Functions 專案進行偵錯時,本機 Functions 主機 (func.exe) 便會開始接聽本機連接埠 (通常是 7071)。 任何可呼叫的函式端點都會寫入輸出,而且您可以使用這些端點來測試函式。 如需詳細資訊,請參閱使用 Azure Functions Core Tools。 第一次從 Visual Studio 啟動函式時,系統會提示您安裝這些工具。

若要在 Visual Studio 中以偵錯模式啟動函式:

  1. 請按 F5。 如果出現提示,接受來自 Visual Studio 之下載及安裝 Azure Functions Core (CLI) 工具的要求。 您可能也需要啟用防火牆例外狀況,工具才能處理 HTTP 要求。

  2. 隨著專案的執行,請像測試部署函數一樣測試程式碼。

    在您在偵錯模式下執行 Visual Studio 時,會依預期遇到中斷點。

如需使用 Visual Studio 的更詳細測試案例,請參閱測試函式

發佈至 Azure

當您將函式專案發佈至 Azure 時,Visual Studio 會使用 zip 部署來部署專案檔。 可能的話,您也應該選取 [Run-From-Package],如此專案就會在部署 (.zip) 套件中執行。 如需詳細資訊,請參閱在 Azure 中從套件檔案執行函式

請勿使用 Web Deploy (msdeploy) 部署至 Azure Functions。

使用下列步驟,將您的專案發佈至 Azure 中的函式應用程式。

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

    Screenshot of publish window.

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

    Screenshot of publish window with specific target.

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

    Screenshot of create a new function app instance.

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

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

    Screenshot of Create App Service dialog.

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

  6. 在 [函式執行個體] 中,請確定已核取 [從封裝檔案執行]。 您的函式應用程式會使用已啟用從套件執行模式的 Zip 部署來部署。 建議採用 Zip 部署來部署函式專案,可提高效能。

    Screenshot of Finish profile creation.

  7. 選取 [完成],然後在 [發佈] 頁面上選取 [發佈],將包含專案檔的套件部署到 Azure 中的新函數應用程式。

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

  8. 在 [發佈] 索引標籤的 [裝載] 區段中,選擇 [在 Azure 入口網站中開啟]。 這會在 Azure 入口網站中開啟新的函數應用程式 Azure 資源。

    Screenshot of Publish success message.

函數應用程式設定

當您發佈專案時,Visual Studio 不會自動上傳這些設定。 若您在 local.settings.json 中所新增了設定,那麼您也必須將所有這些設定新增至 Azure 中的函式應用程式。

將必要設定上傳至 Azure 中函式應用程式的最簡單方式,就是展開 [裝載] 區段旁的三個點,然後選取成功發佈專案之後出現的 [管理 Azure App 服務設定] 連結。

Settings in Publish window

選取此連結會顯示函式應用程式的 [應用程式設定] 對話方塊,您可以在其中新增新的應用程式設定或修改現有的設定。

Application settings

[本機] 會顯示 local.settings.json 檔案中的一個設定值,而 [遠端] 則會顯示 Azure 中函式應用程式中的目前設定值。 選擇 [新增設定] 來建立新的應用程式設定。 使用 [從本機插入值] 連結,將設定值複製到 [遠端] 欄位。 當您選取 [確定] 時,暫止的變更會寫入至本機設定檔案和函式應用程式。

注意

根據預設,local.settings.json 檔案不會簽入原始檔控制。 這表示如果您從原始檔控制複製本機 Functions 專案,那麼專案中就沒有 local.settings.json 檔案。 在此情況下,您必須在專案根目錄中手動建立 local.settings.json 檔案,讓 [應用程式設定] 對話方塊如預期般運作。

您也可以使用下列其中一種方式管理應用程式設定:

遠端偵錯

若要從遠端偵錯函式應用程式,您必須發佈專案的偵錯組態。 您也需要在 Azure 中的函式應用程式中啟用遠端偵錯。

本節會假設您已使用發行組態來將專案發佈至函式應用程式。

遠端偵錯考量

  • 不建議對生產環境服務使用遠端偵錯。
  • 如果您已啟用 Just My Code 偵錯,請將其停用。
  • 進行遠端偵錯時,避免長時間在中斷點停止運作。 Azure 會將停止超過幾分鐘的處理序視為無回應的處理序,並將其關閉。
  • 在偵錯期間,伺服器會將資料傳送至 Visual Studio,進而影響頻寬付費情況。 如需關於頻寬費率的詳細資訊,請參閱 Azure 定價
  • 48 小時後,在您的函式應用程式中會自動停用遠端偵錯。 48 小時之後,您必須重新啟用遠端偵錯。

附加偵錯工具

附加偵錯工具的方式取決於您的執行模式。 在對隔離式背景工作處理序進行偵錯時,您目前需要將遠端偵錯程式附加至個別的 .NET 程序,而且需要進行數個其他的組態步驟。

完成時,您應該停用遠端偵錯

若要將遠端偵錯附加至函式應用程式,且該函式應用程式在與 Functions 主機不同的執行程序中執行:

  1. 從 [發佈] 索引標籤中,選取 [裝載] 區段中的省略符號 (...),然後選擇 [下載發行設定檔]。 此動作會下載發行設定檔的複本,並開啟下載位置。 您需要此檔案,其中包含了認證,可用來附加至您在 Azure 中執行的隔離式背景工作處理序。

    警告

    .publishsettings 檔案包含用來管理您函式應用程式的認證 (未編碼)。 這個檔案的安全性最佳做法是暫時儲存在來源目錄之外 (例如在 Libraries\Documents 資料夾),然後於不再需要之後予以刪除。 惡意使用者若取得 .publishsettings 檔案的存取權,就可以編輯、建立和刪除您的函式應用程式。

  2. 再次從 [發佈] 索引標籤中,選取 [裝載] 區段中的省略符號 (...),然後選擇 [附加偵錯工具]

    Screenshot of attaching the debugger from Visual Studio.

    如果尚未啟用遠端偵錯,Visual Studio 會連線到函數應用程式並啟用遠端偵錯。

    注意

    因為遠端偵錯程式無法連線到主機處理序,所以您可能會看到錯誤。 在任何情況下,預設偵錯都不會中斷您的程式碼。

  3. 回到 Visual Studio,複製 [發佈] 頁面中 [裝載] 底下的 [網站] URL。

  4. 從 [偵錯] 功能表中,選取 [附加至處理序],然後在 [附加至處理序] 視窗中,將 URL 貼到 [連線目標],移除 https:// 並附加連接埠 :4024

    確認您的目標看起來像 <FUNCTION_APP>.azurewebsites.net:4024,然後按 [Enter]鍵。

    Visual Studio attach to process dialog

  5. 如果出現提示,請允許透過本機防火牆存取 Visual Studio。

  6. 當系統提示您輸入認證,而輸入非本機使用者認證時,請選擇不同的帳戶 (Windows 上為 [更多選擇])。 在 Windows 的驗證對話方塊中,提供已發行設定檔中 [電子郵件地址] 和 [密碼] 的 [userName] 和 [userPWD] 值。 在以部署伺服器建立安全連線之後,便會顯示可用的處理序。

    Visual Studio enter credential

  7. 核取 [顯示所有使用者的處理序],然後選擇 [dotnet.exe],並選取 [附加]。 當作業完成時,系統會將您附加至在隔離式背景工作處理序中執行的 C# 類別庫程式碼。 此時,您可以正常地對函式應用程式進行偵錯。

若要使用 Functions 主機將遠端偵錯程式附加至正在執行同處理序的函式應用程式:

  • 從 [發佈] 索引標籤中,選取 [裝載] 區段中的省略符號 (...),然後選擇 [附加偵錯工具]

    Screenshot of attaching the debugger from Visual Studio.

如果尚未啟用遠端偵錯,Visual Studio 會連線到函數應用程式並啟用遠端偵錯。 Visual Studios 也會找出並附加偵錯工具至應用程式的主機處理序。 此時,您可以正常地對函式應用程式進行偵錯。

停用遠端偵錯

完成程式碼的遠端偵錯之後,您應該停用 Azure 入口網站中的遠端偵錯。 再次提醒,遠端偵錯會在 48 小時後自動停用。

  1. 在專案中的 [發佈] 索引標籤中,選取 [裝載] 區段中的省略符號 (...),然後選擇 [在Azure 入口網站中開啟]。 此動作會在部署您專案的 Azure 入口網站中開啟函式應用程式。

  2. 在函式應用程式中,選取 [設定] 下的 [組態],選擇 [一般設定],將 [遠端偵錯] 設定為 [關閉],然後選取 [儲存],並選取 [繼續]

函式應用程式重新啟動之後,您就無法再從遠端連線到遠端處理序。 您可以在 Azure 入口網站中使用這個相同的索引標籤,以便在 Visual Studio 外部啟用遠端偵錯。

監視函式

若要監視您的函式的執行情況,建議您整合您的函式應用程式與 Azure Application Insights。 當您在 Visual Studio 發佈期間建立函數應用程式時,應啟用這項整合。

如果基於某些原因,在發佈期間未完成整合,您仍應為 Azure 中的函數應用程式啟用 Application Insights 整合

若要深入了解如何使用 Application Insights 進行監視,請參閱監視 Azure Functions

測試函式

本節說明如何建立 C# 同處理序模型專案,您可以使用 xUnit 測試該專案。

Testing Azure Functions with C# in Visual Studio

1.安裝程式

使用下列步驟來設定環境,包括支援測試所需的應用程式專案和函式:

  1. 建立新的 Functions 應用程式,並將它命名為 Functions
  2. 從範本建立 HTTP 函式,並將它命名為 MyHttpTrigger
  3. 從範本建立計時器函式,並將它命名為 MyTimerTrigger
  4. 在解決方案中建立 xUnit 測試應用程式 (英文),並將它命名為 Functions.Tests。 移除預設的測試檔案。
  5. 使用 NuGet,從測試應用程式將參考新增至 Microsoft.AspNetCore.Mvc (英文)
  6. Functions.Tests 應用程式參考 Functions 應用程式

現在,既然已建立專案,您可以建立用來執行自動化測試的類別。

2.建立測試類別

每個函式都可接受 ILogger 的執行個體以處理訊息記錄。 有些測試不會記錄訊息,或是沒有考量如何實作記錄。 其他測試需要評估已記錄的訊息,來判斷是否通過測試。

  1. 建立名為 ListLogger 的類別,其中包含測試期間要評估的內部訊息清單。 若要執行必要的 ILogger 介面,類別需要範圍。 下列類別會模擬要傳遞至 ListLogger 類別的測試案例範圍。

  2. Functions.Tests 專案中建立名為 NullScope.cs 的新類別,然後新增此程式碼:

    using System;
    
    namespace Functions.Tests
    {
        public class NullScope : IDisposable
        {
            public static NullScope Instance { get; } = new NullScope();
    
            private NullScope() { }
    
            public void Dispose() { }
        }
    }
    
  3. Functions.Tests 專案中建立名為 ListLogger.cs 的類別,然後新增此程式碼:

    using Microsoft.Extensions.Logging;
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Functions.Tests
    {
        public class ListLogger : ILogger
        {
            public IList<string> Logs;
    
            public IDisposable BeginScope<TState>(TState state) => NullScope.Instance;
    
            public bool IsEnabled(LogLevel logLevel) => false;
    
            public ListLogger()
            {
                this.Logs = new List<string>();
            }
    
            public void Log<TState>(LogLevel logLevel,
                                    EventId eventId,
                                    TState state,
                                    Exception exception,
                                    Func<TState, Exception, string> formatter)
            {
                string message = formatter(state, exception);
                this.Logs.Add(message);
            }
        }
    }
    

    ListLogger 類別實作下列成員,如 ILogger 介面所縮減:

    • BeginScope:設定新增內容至記錄的範圍。 在此案例中,測試只會指向 NullScope 類別上的靜態執行個體,以讓測試運作。

    • IsEnabled:提供的預設值為 false

    • Log:此方法使用提供的 formatter 函式來格式化訊息,並將產生的文字新增到 Logs 集合。

    Logs 集合是 List<string> 的執行個體,且在建構函式中初始化。

  4. Functions.Tests 專案中建立名為 LoggerTypes.cs 的新檔案,然後新增此程式碼:

    namespace Functions.Tests
    {
        public enum LoggerTypes
        {
            Null,
            List
        }
    }
    

    此列舉指定測試使用的記錄器類型。

  5. Functions.Tests 專案中建立名為 TestFactory.cs 的新檔案,然後新增此程式碼:

    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Http.Internal;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Logging.Abstractions;
    using Microsoft.Extensions.Primitives;
    using System.Collections.Generic;
    
    namespace Functions.Tests
    {
        public class TestFactory
        {
            public static IEnumerable<object[]> Data()
            {
                return new List<object[]>
                {
                    new object[] { "name", "Bill" },
                    new object[] { "name", "Paul" },
                    new object[] { "name", "Steve" }
    
                };
            }
    
            private static Dictionary<string, StringValues> CreateDictionary(string key, string value)
            {
                var qs = new Dictionary<string, StringValues>
                {
                    { key, value }
                };
                return qs;
            }
    
            public static HttpRequest CreateHttpRequest(string queryStringKey, string queryStringValue)
            {
                var context = new DefaultHttpContext();
                var request = context.Request;
                request.Query = new QueryCollection(CreateDictionary(queryStringKey, queryStringValue));
                return request;
            }
    
            public static ILogger CreateLogger(LoggerTypes type = LoggerTypes.Null)
            {
                ILogger logger;
    
                if (type == LoggerTypes.List)
                {
                    logger = new ListLogger();
                }
                else
                {
                    logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
                }
    
                return logger;
            }
        }
    }
    

    TestFactory 類別實作下列成員:

    • Data:此屬性會傳回範例資料的 IEnumerable 集合。 索引鍵值組代表傳入查詢字串的值。

    • CreateDictionary:此方法接受金鑰/值組作為引數,且會傳回新的 Dictionary,用來建立 QueryCollection 以代表查詢字串值。

    • CreateHttpRequest:這個方法會建立使用指定之查詢字串參數初始化的 HTTP 要求。

    • CreateLogger:根據記錄器型別,此方法會傳回用於測試的記錄器類別。 ListLogger 會保留已記錄訊息的追蹤以提供給測試的評估使用。

  6. Functions.Tests 專案中建立名為 FunctionsTests.cs 的類別,然後新增此程式碼:

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Logging;
    using Xunit;
    
    namespace Functions.Tests
    {
        public class FunctionsTests
        {
            private readonly ILogger logger = TestFactory.CreateLogger();
    
            [Fact]
            public async void Http_trigger_should_return_known_string()
            {
                var request = TestFactory.CreateHttpRequest("name", "Bill");
                var response = (OkObjectResult)await MyHttpTrigger.Run(request, logger);
                Assert.Equal("Hello, Bill. This HTTP triggered function executed successfully.", response.Value);
            }
    
            [Theory]
            [MemberData(nameof(TestFactory.Data), MemberType = typeof(TestFactory))]
            public async void Http_trigger_should_return_known_string_from_member_data(string queryStringKey, string queryStringValue)
            {
                var request = TestFactory.CreateHttpRequest(queryStringKey, queryStringValue);
                var response = (OkObjectResult)await MyHttpTrigger.Run(request, logger);
                Assert.Equal($"Hello, {queryStringValue}. This HTTP triggered function executed successfully.", response.Value);
            }
    
            [Fact]
            public void Timer_should_log_message()
            {
                var logger = (ListLogger)TestFactory.CreateLogger(LoggerTypes.List);
                new MyTimerTrigger().Run(null, logger);
                var msg = logger.Logs[0];
                Assert.Contains("C# Timer trigger function executed at", msg);
            }
        }
    }
    

    成員在此案例中的實作為:

    • Http_trigger_should_return_known_string:這項測試會建立對 HTTP 函式的要求 (具有 name=Bill 的查詢字串值),並檢查是否傳回預期的回應。

    • Http_trigger_should_return_string_from_member_data:此測試使用 xUnit 屬性以提供範例資料給 HTTP 函式。

    • Timer_should_log_message:此測試會建立 ListLogger 的執行個體,並將它傳遞給計時器函式。 一旦函式執行之後,便會檢查記錄以確保是否存在預期的訊息。

  7. 若要存取測試中的應用程式設定,您可以將具有模擬環境變數值的 IConfiguration 執行個體插入函式中。

3.執行測試

若要執行測試,請瀏覽至 [測試總管],然後選取 [在檢視中執行所有測試]

Testing Azure Functions with C# in Visual Studio

4.偵錯測試

若要針對測試偵錯,請在測試上設定中斷點,瀏覽至 [測試總管] 然後選取 [執行] > [對上一個回合偵錯]

下一步

如需 Azure Functions Core Tools 的詳細資訊,請參閱使用 Azure Functions Core Tools