分享方式:


快速入門:使用 Azure Functions 和 SignalR Service 透過 C 建立顯示 GitHub 星號計數的應用程式#

在本文中,您將瞭解如何使用 SignalR Service 和 Azure Functions 來建置具有 C# 的無伺服器應用程式,以將訊息廣播至用戶端。

注意

您可以從 GitHub 取得本文所述的程式代碼。

必要條件

本快速入門需要下列必要條件:

建立 Azure SignalR 服務實例

在本節中,您會建立基本 Azure SignalR 執行個體,以用於您的應用程式。 下列步驟會使用 Azure 入口網站來建立新的執行個體,但您也可以使用 Azure CLI。 如需詳細資訊,請參閱 Azure SignalR Service CLI 參考中的 az signalr create 命令。

  1. 登入 Azure 入口網站
  2. 在頁面的左側,選取 [+ 建立資源]
  3. 在 [建立資源] 頁面上的 [搜尋服務和市集] 文字方塊中,輸入 signalr,然後從清單中選取 [SignalR Service]
  4. 在 [SignalR Service] 頁面上,選取 [建立]
  5. 在 [基本] 索引標籤上,您會輸入新 SignalR Service 執行個體的重要資訊。 輸入下列值:
欄位 建議的值 描述
訂用帳戶 選擇您的訂用帳戶 選取您要用來建立新 SignalR Service 執行個體的訂用帳戶。
資源群組 建立名為 SignalRTestResources 的新資源群組 選取或建立 SignalR 資源的資源群組。 針對本教學課程建立新的資源群組,而不是使用現有的資源群組,會很有用。 若要在完成本教學課程之後釋出資源,請刪除資源群組。

刪除資源群組同時會刪除群組所屬的所有資源。 此動作無法復原。 刪除資源群組之前,請確定其不包含您想要保留的資源。

如需詳細資訊,請參閱 使用資源群組來管理您的 Azure 資源
資源名稱 testsignalr 輸入要對 SignalR 資源使用的唯一資源名稱。 如果您的區域中已採用 testsignalr,請新增數字或字元,直到成為唯一的名稱為止。

名稱必須是 1 到 63 個字元的字串,而且只能包含數字、字母和連字號 (-) 字元。 名稱的開頭或結尾不能是連字號字元,且連續連字號字元無效。
區域 選擇您的區域 選取新 SignalR Service 執行個體的適當區域。

Azure SignalR Service 目前不適用於所有區域。 如需詳細資訊,請參閱 Azure SignalR 區域可用性
定價層 選取 [變更],然後選擇 [免費 (僅限開發/測試)]。 選擇 [選取] 來確認您選擇的定價層。 Azure SignalR Service 有三個定價層:免費、標準和進階。 除非必要條件中另有說明,否則教學課程會使用 [免費] 層。

如需有關階層與定價之間功能差異的詳細資訊,請參閱 Azure SignalR Service 定價
服務模式 選擇適當的服務模式 當您在 Web 應用程式中裝載 SignalR 中樞邏輯並使用 SignalR 服務做為 Proxy 時,請使用 [預設值]。 當您使用 Azure Functions 之類的無伺服器技術來裝載 SignalR 中樞邏輯時,請使用 [無伺服器]

[傳統] 模式僅適用於回溯相容性,不建議使用。

如需詳細資訊,請參閱 Azure SignalR Service 中的服務模式

您不需要針對 SignalR 教學課程變更 [網路] 和 [標籤] 索引標籤上的設定。

  1. 選取 [基本] 索引標籤底部的 [檢閱 + 建立] 按鈕。
  2. 在 [檢閱 + 建立] 索引標籤上,檢閱這些值,然後選取 [建立]。 需要數分鐘才能完成部署。
  3. 部署完成後,請選取 [移至資源] 按鈕。
  4. 在 SignalR 資源頁面上,從左側功能表的 [設定] 底下選取 [金鑰]
  5. 複製主索引鍵的 [連接字串]。 稍後在本教學課程中,您需要此連接字串來設定您的應用程式。

在本機設定並執行 Azure 函式

您需要此步驟的 Azure Functions Core Tools。

  1. 建立空的目錄,並使用命令行變更至目錄。

  2. 初始化新專案。

    # Initialize a function project
    func init --worker-runtime dotnet
    
    # Add SignalR Service package reference to the project
    dotnet add package Microsoft.Azure.WebJobs.Extensions.SignalRService
    
  3. 使用程式代碼編輯器,建立名稱 為Function.cs的新檔案。 將下列程式代碼新增至 Function.cs

    using System;
    using System.IO;
    using System.Linq;
    using System.Net.Http;
    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.SignalRService;
    using Newtonsoft.Json;
    
    namespace CSharp
    {
        public static class Function
        {
            private static HttpClient httpClient = new HttpClient();
            private static string Etag = string.Empty;
            private static string StarCount = "0";
    
            [FunctionName("index")]
            public static IActionResult GetHomePage([HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req, ExecutionContext context)
            {
                var path = Path.Combine(context.FunctionAppDirectory, "content", "index.html");
                return new ContentResult
                {
                    Content = File.ReadAllText(path),
                    ContentType = "text/html",
                };
            }
    
            [FunctionName("negotiate")]
            public static SignalRConnectionInfo Negotiate(
                [HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req,
                [SignalRConnectionInfo(HubName = "serverless")] SignalRConnectionInfo connectionInfo)
            {
                return connectionInfo;
            }
    
            [FunctionName("broadcast")]
            public static async Task Broadcast([TimerTrigger("*/5 * * * * *")] TimerInfo myTimer,
            [SignalR(HubName = "serverless")] IAsyncCollector<SignalRMessage> signalRMessages)
            {
                var request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/azure/azure-signalr");
                request.Headers.UserAgent.ParseAdd("Serverless");
                request.Headers.Add("If-None-Match", Etag);
                var response = await httpClient.SendAsync(request);
                if (response.Headers.Contains("Etag"))
                {
                    Etag = response.Headers.GetValues("Etag").First();
                }
                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    var result = JsonConvert.DeserializeObject<GitResult>(await response.Content.ReadAsStringAsync());
                    StarCount = result.StarCount;
                }
    
                await signalRMessages.AddAsync(
                    new SignalRMessage
                    {
                        Target = "newMessage",
                        Arguments = new[] { $"Current star count of https://github.com/Azure/azure-signalr is: {StarCount}" }
                    });
            }
    
            private class GitResult
            {
                [JsonRequired]
                [JsonProperty("stargazers_count")]
                public string StarCount { get; set; }
            }
        }
    }
    

    Function.cs中的 程式 代碼有三個函式:

    • GetHomePage 用來取得網站作為用戶端。
    • Negotiate 用戶端會使用 來取得存取令牌。
    • Broadcast 會定期呼叫 以從 GitHub 取得星號計數,然後將訊息廣播給所有用戶端。
  4. 此範例的用戶端介面是網頁。 我們從檔案 content/index.html 讀取 HTML 內容,以使用 GetHomePage 函式轉譯網頁。 現在,讓我們使用下列內容,content在子目錄中建立此index.html

    <html>
    
    <body>
      <h1>Azure SignalR Serverless Sample</h1>
      <div id="messages"></div>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.7/signalr.min.js"></script>
      <script>
        let messages = document.querySelector('#messages');
        const apiBaseUrl = window.location.origin;
        const connection = new signalR.HubConnectionBuilder()
            .withUrl(apiBaseUrl + '/api')
            .configureLogging(signalR.LogLevel.Information)
            .build();
          connection.on('newMessage', (message) => {
            document.getElementById("messages").innerHTML = message;
          });
    
          connection.start()
            .catch(console.error);
      </script>
    </body>
    
    </html>
    
  5. 更新 您的 *.csproj ,使組建輸出資料夾中的內容頁面。

    <ItemGroup>
      <None Update="content/index.html">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </None>
    </ItemGroup>
    
  6. Azure Functions 需要記憶體帳戶才能運作。 您可以安裝並執行 Azure 儲存體 模擬器或者 ,您可以使用下列命令來更新 設定以使用實際的記憶體帳戶:

    func settings add AzureWebJobsStorage "<storage-connection-string>"
    
  7. 現在幾乎完成了。 最後一個步驟是將 SignalR Service 的 連接字串 設定為 Azure 函式設定。

    1. 確認 SignalR Service 實例已成功建立,方法是在入口網站頂端的搜尋方塊中搜尋其名稱。 選取該執行個體以開啟它。

      搜尋 SignalR 服務實例

    2. 選取 [金鑰] 以檢視 SignalR Service 實例的 連接字串。

      醒目提示主要 連接字串 的螢幕快照。

    3. 複製主要 連接字串,然後執行下列命令:

      func settings add AzureSignalRConnectionString "<signalr-connection-string>"
      
  8. 在本機執行 Azure 函式:

    func start
    

    在 Azure 函式在本機執行之後,請開啟 http://localhost:7071/api/index,您可以看到目前的星號計數。 如果您在 GitHub 中以星號或取消星號,您就會每隔幾秒鐘重新整理一次星號計數。

清除資源

如果您不打算繼續使用此應用程式,請使用下列步驟刪除本快速入門所建立的所有資源,因此不會產生任何費用:

  1. 在 Azure 入口網站中選取最左側的 [資源群組],然後選取您所建立的資源群組。 或者,您可以使用搜尋方塊依其名稱尋找資源群組。

  2. 在開啟的視窗中,選取資源群組,然後按兩下 [ 刪除資源群組]。

  3. 在新視窗中輸入要刪除之資源群組的名稱,然後按一下 [刪除]

有問題嗎? 請嘗試疑難解答指南,或讓我們知道

下一步

在本快速入門中,您已在本機建置並執行即時無伺服器應用程式。 接下來,深入瞭解用戶端與 Azure Functions 與 Azure SignalR Service 之間的雙向通訊。