教學課程:開始使用 ASP.NET Core SignalR
本教學課程說明如何使用 SignalR 建置即時應用程式的基本概念。 您會了解如何:
- 建立 Web 專案。
- SignalR新增用戶端程式庫。
- 建立中 SignalR 樞。
- 將專案設定為使用 SignalR 。
- 新增程式碼,以將訊息從任何用戶端傳送至所有連線的用戶端。
最後,您會有一個運作正常的聊天應用程式:
必要條件
- Visual Studio 2022 和 ASP.NET 與 Web 開發工作負載。
建立 Web 應用程式專案
啟動 Visual Studio 2022,然後選取 [ 建立新專案]。
在 [建立新專案] 對話方塊中,選取[ASP.NET Core Web 應用程式],然後選取 [下一步]。
在 [ 設定新專案 ] 對話方塊中,輸入
SignalRChat
[專案名稱]。 請務必將專案SignalR命名為 Chat,包括比對大寫,因此當您複製並貼上範例程式碼時,命名空間將會相符。選取 [下一步]。
在 [其他資訊] 對話方塊中,選取 [.NET 6.0 (長期支援) ],然後選取 [ 建立]。
SignalR新增用戶端程式庫
伺服器 SignalR 程式庫包含在 ASP.NET Core共用架構中。 JavaScript 用戶端程式庫不會自動包括在專案中。 在本教學課程中,請使用程式庫管理員 (LibMan) 從 unpkg取得用戶端程式庫。 unpkg
是 npm上所有專案的快速全域內容傳遞網路。
- 在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [新增]>[用戶端程式庫]。
- 在 [ 新增Client-Side程式庫 ] 對話方塊中:
- 針對提供者選取unpkg
- 針對 [程式庫] 輸入
@microsoft/signalr@latest
- 選取 [選擇特定檔案]、展開 dist/browser 資料夾,然後選取
signalr.js
和signalr.min.js
。 - 將 [目標位置 ] 設定為 wwwroot/js/signalr/
- 選取 [安裝]
LibMan 會建立 wwwroot/js/signalr 資料夾,並將選取的檔案複製到其中。
建立中 SignalR 樞
中樞類別可提供作為高階管線,用來處理用戶端/伺服器通訊。
- 在 [ SignalR 聊天專案] 資料夾中,建立 Hubs 資料夾。
- 在 Hubs 資料夾中,使用下列程式碼建立
ChatHub
類別:
using Microsoft.AspNetCore.SignalR;
namespace SignalRChat.Hubs
{
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
}
類別 ChatHub
繼承自 SignalRHub 類別。 Hub
類別管理連線、群組和傳訊。
連線的用戶端可以呼叫 SendMessage
方法將訊息傳送至所有用戶端。 本教學課程稍後將示範呼叫該方法的 JavaScript 用戶端程式碼。 SignalR 程式碼是非同步,可提供最大延展性。
設定 SignalR
伺服器 SignalR 必須設定為將要求傳遞 SignalR 至 SignalR 。 將下列醒目提示的程式碼新增至 Program.cs
檔案。
using SignalRChat.Hubs;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.MapHub<ChatHub>("/chatHub");
app.Run();
上述醒目提示的程式碼會新增 SignalR 至 ASP.NET Core相依性插入和路由系統。
新增 SignalR 用戶端程式代碼
將 中
Pages/Index.cshtml
的內容取代為下列程式碼:@page <div class="container"> <div class="row"> </div> <div class="row"> <div class="col-2">User</div> <div class="col-4"><input type="text" id="userInput" /></div> </div> <div class="row"> <div class="col-2">Message</div> <div class="col-4"><input type="text" id="messageInput" /></div> </div> <div class="row"> </div> <div class="row"> <div class="col-6"> <input type="button" id="sendButton" value="Send Message" /> </div> </div> </div> <div class="row"> <div class="col-12"> <hr /> </div> </div> <div class="row"> <div class="col-6"> <ul id="messagesList"></ul> </div> </div> <script src="~/js/signalr/dist/browser/signalr.js"></script> <script src="~/js/chat.js"></script>
上述標記:
- 建立文字方塊和提交按鈕。
- 使用 建立清單
id="messagesList"
,以顯示從中樞接收的 SignalR 訊息。 - 包含 的 SignalR 腳本參考,
chat.js
並在下一個步驟中建立應用程式程式碼。
在 wwwroot/js 資料夾中,使用下列程式碼建立
chat.js
檔案:"use strict"; var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build(); //Disable the send button until connection is established. document.getElementById("sendButton").disabled = true; connection.on("ReceiveMessage", function (user, message) { var li = document.createElement("li"); document.getElementById("messagesList").appendChild(li); // We can assign user-supplied strings to an element's textContent because it // is not interpreted as markup. If you're assigning in any other way, you // should be aware of possible script injection concerns. li.textContent = `${user} says ${message}`; }); connection.start().then(function () { document.getElementById("sendButton").disabled = false; }).catch(function (err) { return console.error(err.toString()); }); document.getElementById("sendButton").addEventListener("click", function (event) { var user = document.getElementById("userInput").value; var message = document.getElementById("messageInput").value; connection.invoke("SendMessage", user, message).catch(function (err) { return console.error(err.toString()); }); event.preventDefault(); });
上述 JavaScript:
- 建立並啟動連線。
- 新增處理常式至提交按鈕,以將訊息傳送至中樞。
- 新增處理常式至連線物件,以從中樞接收訊息,並將它們新增至清單。
執行應用程式
- 按 CTRL+F5 即可執行應用程式而不偵錯。
- 從網址列複製 URL,開啟另一個瀏覽器執行個體或索引標籤,然後將 URL 貼入網址列。
- 選擇任一個瀏覽器,輸入名稱和訊息,然後選取 [傳送訊息] 按鈕。 名稱和訊息會立即顯示在兩個頁面上。
提示
如果應用程式無法運作,請開啟您的瀏覽器開發人員工具 (F12),然後移至主控台。 您可能會看到與 HTML 和 JavaScript 程式碼相關的錯誤。 例如,假設您放入
signalr.js
與導向不同的資料夾。 在此情況下,該檔案的參考無法運作,您會在主控台中看到 404 錯誤。如果您在 Chrome 中收到錯誤ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY,請執行下列命令來更新您的開發憑證:
dotnet dev-certs https --clean dotnet dev-certs https --trust
發佈至 Azure
如需部署至 Azure 的資訊,請參閱 快速入門:部署 ASP.NET Web 應用程式。
本教學課程說明如何使用 SignalR 建置即時應用程式的基本概念。 您會了解如何:
- 建立 Web 專案。
- SignalR新增用戶端程式庫。
- 建立中 SignalR 樞。
- 將專案設定為使用 SignalR 。
- 新增程式碼,以將訊息從任何用戶端傳送至所有連線的用戶端。
最後,您會有一個運作正常的聊天應用程式:
必要條件
Visual Studio 2019 16.4 或更新版本,其中包含 ASP.NET 和網頁程式開發工作負載
建立 Web 應用程式專案
- 從功能表中,選取 [ 檔案 > 新增專案]。
- 在 [建立新專案] 對話方塊中,選取 [ASP.NET Core Web 應用程式],然後選取 [下一步]。
- 在 [設定您的新專案] 對話方塊中,將專案SignalR 命名為 [聊天],然後選取 [建立]。
- 在[建立新的 ASP.NET Core Web 應用程式] 對話方塊中,選取[.NET Core] 並ASP.NET Core 3.1。
- 選取 [Web 應用程式 ] 以建立使用 Razor Pages 的專案,然後選取 [ 建立]。
SignalR新增用戶端程式庫
伺服器 SignalR 程式庫包含在 ASP.NET Core 3.1 共用架構中。 JavaScript 用戶端程式庫不會自動包括在專案中。 針對此教學課程,您會使用程式庫管理員 (LibMan) 從 unpkg 取得用戶端程式庫。 unpkg 是一種內容傳遞網路 (CDN) ,可傳遞 npm 中Node.js套件管理員中找到的任何專案。
- 在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [新增]>[用戶端程式庫]。
- 在 [新增用戶端程式庫] 對話方塊中,針對 [提供者] 選取 [unpkg]。
- 針對 [程式庫] 輸入
@microsoft/signalr@latest
。 - 選取 [選擇特定檔案]、展開 dist/browser 資料夾,然後選取
signalr.js
和signalr.min.js
。 - 將 [目標位置 ] 設定為 wwwroot/js/signalr/
- 選取 [安裝]
LibMan 會建立 wwwroot/js/signalr 資料夾,並將選取的檔案複製到其中。
建立中 SignalR 樞
中樞類別可提供作為高階管線,用來處理用戶端/伺服器通訊。
- 在 [ SignalR 聊天專案] 資料夾中,建立 Hubs 資料夾。
- 在 Hubs 資料夾中,使用下列程式碼建立
ChatHub.cs
檔案:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
namespace SignalRChat.Hubs
{
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
}
類別 ChatHub
繼承自 SignalRHub
類別。 Hub
類別管理連線、群組和傳訊。
連線的用戶端可以呼叫 SendMessage
方法將訊息傳送至所有用戶端。 本教學課程稍後將示範呼叫該方法的 JavaScript 用戶端程式碼。 SignalR 程式碼是非同步,可提供最大延展性。
設定 SignalR
伺服器 SignalR 必須設定為將要求傳遞 SignalR 至 SignalR 。
將下列醒目提示的程式碼新增至
Startup.cs
檔案。using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using SignalRChat.Hubs; namespace SignalRChat { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddSignalR(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapHub<ChatHub>("/chatHub"); }); } } }
這些變更會新增 SignalR 至 ASP.NET Core相依性插入和路由系統。
新增 SignalR 用戶端程式代碼
將 中
Pages/Index.cshtml
的內容取代為下列程式碼:@page <div class="container"> <div class="row"> </div> <div class="row"> <div class="col-2">User</div> <div class="col-4"><input type="text" id="userInput" /></div> </div> <div class="row"> <div class="col-2">Message</div> <div class="col-4"><input type="text" id="messageInput" /></div> </div> <div class="row"> </div> <div class="row"> <div class="col-6"> <input type="button" id="sendButton" value="Send Message" /> </div> </div> </div> <div class="row"> <div class="col-12"> <hr /> </div> </div> <div class="row"> <div class="col-6"> <ul id="messagesList"></ul> </div> </div> <script src="~/js/signalr/dist/browser/signalr.js"></script> <script src="~/js/chat.js"></script>
上述程式碼:
- 建立名稱和訊息文字的文字方塊,以及提交按鈕。
- 使用 建立清單
id="messagesList"
,以顯示從中樞接收的 SignalR 訊息。 - 包含 的 SignalR 腳本參考,以及
chat.js
您在下一個步驟中建立的應用程式程式碼。
在 wwwroot/js 資料夾中,使用下列程式碼建立
chat.js
檔案:"use strict"; var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build(); //Disable send button until connection is established document.getElementById("sendButton").disabled = true; connection.on("ReceiveMessage", function (user, message) { var li = document.createElement("li"); document.getElementById("messagesList").appendChild(li); // We can assign user-supplied strings to an element's textContent because it // is not interpreted as markup. If you're assigning in any other way, you // should be aware of possible script injection concerns. li.textContent = `${user} says ${message}`; }); connection.start().then(function () { document.getElementById("sendButton").disabled = false; }).catch(function (err) { return console.error(err.toString()); }); document.getElementById("sendButton").addEventListener("click", function (event) { var user = document.getElementById("userInput").value; var message = document.getElementById("messageInput").value; connection.invoke("SendMessage", user, message).catch(function (err) { return console.error(err.toString()); }); event.preventDefault(); });
上述程式碼:
- 建立並啟動連線。
- 新增處理常式至提交按鈕,以將訊息傳送至中樞。
- 新增處理常式至連線物件,以從中樞接收訊息,並將它們新增至清單。
執行應用程式
- 按 CTRL+F5 即可執行應用程式而不偵錯。
- 從網址列複製 URL,開啟另一個瀏覽器執行個體或索引標籤,然後將 URL 貼入網址列。
- 選擇任一個瀏覽器,輸入名稱和訊息,然後選取 [傳送訊息] 按鈕。 名稱和訊息會立即顯示在兩個頁面上。
提示
如果應用程式無法運作,請開啟您的瀏覽器開發人員工具 (F12),然後移至主控台。 您可能會看到與 HTML 和 JavaScript 程式碼相關的錯誤。 例如,假設您放入
signalr.js
與導向不同的資料夾。 在此情況下,該檔案的參考無法運作,您會在主控台中看到 404 錯誤。如果您在 Chrome 中收到錯誤ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY,請執行下列命令來更新您的開發憑證:
dotnet dev-certs https --clean dotnet dev-certs https --trust
發佈至 Azure
如需部署至 Azure 的資訊,請參閱 快速入門:部署 ASP.NET Web 應用程式。