结合使用 ASP.NET Core SignalR 和 Blazor

本教程介绍结合使用 SignalR 和 Blazor 生成实时应用的基础知识。

了解如何:

  • 创建 Blazor 项目
  • 添加 SignalR 客户端库
  • 添加 SignalR 集线器
  • 添加 SignalR 服务和 SignalR 中心的终结点
  • 添加用于聊天的 Razor 组件代码

在本教程结束时,你将拥有一个正常运行的聊天应用。

先决条件

示例应用

本教程不需要下载教程的示例聊天应用。 示例应用是按照本教程的步骤生成的最终工作应用。

查看或下载示例代码

创建托管 Blazor WebAssembly 应用

按照所选工具的指南进行操作:

注意

需要 Visual Studio 2022 或更高版本以及 .NET Core SDK 6.0.0 或更高版本。

  1. 创建新项目。

  2. 选择“Blazor WebAssembly 应用”模板。 选择“下一步”。

  3. 在“项目名称”字段中键入 BlazorWebAssemblySignalRApp。 确认“位置”条目正确无误或为项目提供位置。 选择“下一步”。

  4. 在“其他信息”对话框中,选中“托管的 ASP.NET Core”复选框。

  5. 选择“创建”。

  6. 确认已创建托管 Blazor WebAssembly 应用:在解决方案资源管理器中,确认是否存在 Client 项目和 Server 项目。 如果两个项目不存在,请重新开始并在选择“创建”之前确认已选中“ASP.NET Core 托管”复选框。

添加 SignalR 客户端库

  1. 在“解决方案资源管理器”中,右键单击 BlazorWebAssemblySignalRApp.Client 项目,然后选择“管理 NuGet 包” 。

  2. 在“管理 NuGet 包”对话框中,确认“包源”设置为“nuget.org” 。

  3. 选择“浏览”后,在搜索框中键入“Microsoft.AspNetCore.SignalR.Client”。

  4. 在搜索结果中,选择 Microsoft.AspNetCore.SignalR.Client 包。 将版本设置为与应用共享框架匹配的版本。 选择“安装” 。

  5. 如果出现“预览更改”对话框,则选择“确定”。

  6. 如果出现“许可证接受”对话框,如果你同意许可条款,请选择“我接受”。

添加 SignalR 集线器

BlazorWebAssemblySignalRApp.Server 项目中,创建 Hubs(复数)文件夹,并添加以下 ChatHub 类 (Hubs/ChatHub.cs):

using Microsoft.AspNetCore.SignalR;

namespace BlazorWebAssemblySignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

为 SignalR 中心添加服务和终结点

  1. BlazorWebAssemblySignalRApp.Server 项目中打开 Program.cs 文件。

  2. ChatHub 类的命名空间添加到文件顶部:

    using BlazorWebAssemblySignalRApp.Server.Hubs;
    
  3. 将 SignalR 和响应压缩中间件服务添加到 Program.cs

    builder.Services.AddSignalR();
    builder.Services.AddResponseCompression(opts =>
    {
        opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            new[] { "application/octet-stream" });
    });
    
  4. Program.cs中:

    • 使用处理管道的配置顶部的“响应压缩中间件”。
    • 在控制器终结点和客户端回退之间,为中心添加一个终结点。
    app.UseResponseCompression();
    
    if (app.Environment.IsDevelopment())
    {
        app.UseWebAssemblyDebugging();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseBlazorFrameworkFiles();
    app.UseStaticFiles();
    
    app.UseRouting();
    
    app.MapRazorPages();
    app.MapControllers();
    app.MapHub<ChatHub>("/chathub");
    app.MapFallbackToFile("index.html");
    
    app.Run();
    

添加用于聊天的 Razor 组件代码

  1. BlazorWebAssemblySignalRApp.Client 项目中打开 Pages/Index.razor 文件。

  2. 将标记替换为以下代码:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager NavigationManager
    @implements IAsyncDisposable
    
    <PageTitle>Index</PageTitle>
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection? hubConnection;
        private List<string> messages = new List<string>();
        private string? userInput;
        private string? messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                StateHasChanged();
            });
    
            await hubConnection.StartAsync();
        }
    
        private async Task Send()
        {
            if (hubConnection is not null)
                {
                    await hubConnection.SendAsync("SendMessage", userInput, messageInput);
                }
        }
    
        public bool IsConnected =>
            hubConnection?.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            if (hubConnection is not null)
            {
                await hubConnection.DisposeAsync();
            }
        }
    }
    

运行应用

按照工具的指南进行操作:

  1. 在“解决方案资源管理器”中,选择 BlazorWebAssemblySignalRApp.Server 项目。 按 F5 来运行应用并进行调试,或者按 Ctrl+F5 (Windows)/+F5 (macOS) 来运行应用但不调试。

    重要

    执行托管的 Blazor WebAssembly 应用时,请从解决方案的 Server 项目运行应用。

  2. 从地址栏复制 URL,打开另一个浏览器实例或选项卡,并在地址栏中粘贴该 URL。

  3. 选择任一浏览器,输入名称和消息,然后选择按钮发送消息。 两个页面上立即显示名称和消息:

    SignalRBlazor sample app open in two browser windows showing exchanged messages.

    引文:Star Trek VI: The Undiscovered Country ©1991 Paramount

创建 Blazor Server 应用

按照所选工具的指南进行操作:

注意

需要 Visual Studio 2022 或更高版本以及 .NET Core SDK 6.0.0 或更高版本。

  1. 创建新项目。

  2. 选择“Blazor Server 应用”模板。 选择“下一步”。

  3. 在“项目名称”字段中键入 BlazorServerSignalRApp。 确认“位置”条目正确无误或为项目提供位置。 选择“下一步”。

  4. 选择“创建”。

添加 SignalR 客户端库

  1. 在“解决方案资源管理器”中,右键单击 BlazorServerSignalRApp 项目,然后选择“管理 NuGet 包” 。

  2. 在“管理 NuGet 包”对话框中,确认“包源”设置为“nuget.org” 。

  3. 选择“浏览”后,在搜索框中键入“Microsoft.AspNetCore.SignalR.Client”。

  4. 在搜索结果中,选择 Microsoft.AspNetCore.SignalR.Client 包。 将版本设置为与应用共享框架匹配的版本。 选择“安装” 。

  5. 如果出现“预览更改”对话框,则选择“确定”。

  6. 如果出现“许可证接受”对话框,如果你同意许可条款,请选择“我接受”。

添加 SignalR 集线器

创建 Hubs(复数)文件夹,并添加以下 ChatHub 类 (Hubs/ChatHub.cs):

using Microsoft.AspNetCore.SignalR;

namespace BlazorServerSignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

为 SignalR 中心添加服务和终结点

  1. 打开 Program.cs 文件。

  2. Microsoft.AspNetCore.ResponseCompressionChatHub 类的命名空间添加到文件的顶部:

    using Microsoft.AspNetCore.ResponseCompression;
    using BlazorServerSignalRApp.Hubs;
    
  3. 将响应压缩中间件服务添加到 Program.cs

    builder.Services.AddRazorPages();
    builder.Services.AddServerSideBlazor();
    builder.Services.AddSingleton<WeatherForecastService>();
    builder.Services.AddResponseCompression(opts =>
    {
        opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            new[] { "application/octet-stream" });
    });
    
  4. Program.cs中:

    • 使用处理管道的配置顶部的“响应压缩中间件”。

    • 在用于映射 Blazor 中心的终结点和客户端回退终结点之间,为中心添加一个终结点:

      app.MapHub<ChatHub>("/chathub");
      
    app.UseResponseCompression();
    
    if (!app.Environment.IsDevelopment())
    {
        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.MapBlazorHub();
    app.MapHub<ChatHub>("/chathub");
    app.MapFallbackToPage("/_Host");
    
    app.Run();
    

添加用于聊天的 Razor 组件代码

  1. 打开 Pages/Index.razor 文件。

  2. 将标记替换为以下代码:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager NavigationManager
    @implements IAsyncDisposable
    
    <PageTitle>Index</PageTitle>
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection? hubConnection;
        private List<string> messages = new List<string>();
        private string? userInput;
        private string? messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                InvokeAsync(StateHasChanged);
            });
    
            await hubConnection.StartAsync();
        }
    
        private async Task Send()
        {
            if (hubConnection is not null)
                {
                    await hubConnection.SendAsync("SendMessage", userInput, messageInput);
                }
        }
    
        public bool IsConnected =>
            hubConnection?.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            if (hubConnection is not null)
            {
                await hubConnection.DisposeAsync();
            }
        }
    }
    

运行应用

按照工具的指南进行操作:

  1. F5 来运行应用并进行调试,或者按 Ctrl+F5 (Windows)/+F5 (macOS) 来运行应用但不调试。

  2. 从地址栏复制 URL,打开另一个浏览器实例或选项卡,并在地址栏中粘贴该 URL。

  3. 选择任一浏览器,输入名称和消息,然后选择按钮发送消息。 两个页面上立即显示名称和消息:

    SignalRBlazor sample app open in two browser windows showing exchanged messages.

    引文:Star Trek VI: The Undiscovered Country ©1991 Paramount

后续步骤

在本教程中,你了解了如何执行以下操作:

  • 创建 Blazor 项目
  • 添加 SignalR 客户端库
  • 添加 SignalR 集线器
  • 添加 SignalR 服务和 SignalR 中心的终结点
  • 添加用于聊天的 Razor 组件代码

若要了解有关生成 Blazor 应用的详细信息,请参阅 Blazor 文档:

其他资源

了解如何:

  • 创建 Blazor 项目
  • 添加 SignalR 客户端库
  • 添加 SignalR 集线器
  • 添加 SignalR 服务和 SignalR 中心的终结点
  • 添加用于聊天的 Razor 组件代码

在本教程结束时,你将拥有一个正常运行的聊天应用。

先决条件

示例应用

本教程不需要下载教程的示例聊天应用。 示例应用是按照本教程的步骤生成的最终工作应用。

查看或下载示例代码

创建托管 Blazor WebAssembly 应用

按照所选工具的指南进行操作:

注意

需要 Visual Studio 16.10 或更高版本以及 .NET Core SDK 5.0.0 或更高版本。

  1. 创建新项目。

  2. 选择“Blazor WebAssembly 应用”模板。 选择“下一步”。

  3. 在“项目名称”字段中键入 BlazorWebAssemblySignalRApp。 确认“位置”条目正确无误或为项目提供位置。 选择“下一步”。

  4. 在“其他信息”对话框中,选中“托管的 ASP.NET Core”复选框。

  5. 选择“创建”。

添加 SignalR 客户端库

  1. 在“解决方案资源管理器”中,右键单击 BlazorWebAssemblySignalRApp.Client 项目,然后选择“管理 NuGet 包” 。

  2. 在“管理 NuGet 包”对话框中,确认“包源”设置为“nuget.org” 。

  3. 选择“浏览”后,在搜索框中键入“Microsoft.AspNetCore.SignalR.Client”。

  4. 在搜索结果中,选择 Microsoft.AspNetCore.SignalR.Client 包。 将版本设置为与应用共享框架匹配的版本。 选择“安装” 。

  5. 如果出现“预览更改”对话框,则选择“确定”。

  6. 如果出现“许可证接受”对话框,如果你同意许可条款,请选择“我接受”。

添加 SignalR 集线器

BlazorWebAssemblySignalRApp.Server 项目中,创建 Hubs(复数)文件夹,并添加以下 ChatHub 类 (Hubs/ChatHub.cs):

using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;

namespace BlazorWebAssemblySignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

为 SignalR 中心添加服务和终结点

  1. BlazorWebAssemblySignalRApp.Server 项目中打开 Startup.cs 文件。

  2. ChatHub 类的命名空间添加到文件顶部:

    using BlazorWebAssemblySignalRApp.Server.Hubs;
    
  3. 将 SignalR 和响应压缩中间件服务添加到 Startup.ConfigureServices

    services.AddSignalR();
    services.AddResponseCompression(opts =>
    {
        opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            new[] { "application/octet-stream" });
    });
    
  4. Startup.Configure中:

    • 使用处理管道的配置顶部的“响应压缩中间件”。
    • 在控制器终结点和客户端回退之间,为中心添加一个终结点。
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseResponseCompression();
    
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseWebAssemblyDebugging();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
        app.UseBlazorFrameworkFiles();
        app.UseStaticFiles();
    
        app.UseRouting();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
            endpoints.MapControllers();
            endpoints.MapHub<ChatHub>("/chathub");
            endpoints.MapFallbackToFile("index.html");
        });
    }
    

添加用于聊天的 Razor 组件代码

  1. BlazorWebAssemblySignalRApp.Client 项目中打开 Pages/Index.razor 文件。

  2. 将标记替换为以下代码:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager NavigationManager
    @implements IAsyncDisposable
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection hubConnection;
        private List<string> messages = new List<string>();
        private string userInput;
        private string messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                StateHasChanged();
            });
    
            await hubConnection.StartAsync();
        }
    
        async Task Send() =>
            await hubConnection.SendAsync("SendMessage", userInput, messageInput);
    
        public bool IsConnected =>
            hubConnection.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            if (hubConnection is not null)
            {
                await hubConnection.DisposeAsync();
            }
        }
    }
    

运行应用

按照工具的指南进行操作:

  1. 在“解决方案资源管理器”中,选择 BlazorWebAssemblySignalRApp.Server 项目。 按 F5 来运行应用并进行调试,或者按 Ctrl+F5 (Windows)/+F5 (macOS) 来运行应用但不调试。

    重要

    执行托管的 Blazor WebAssembly 应用时,请从解决方案的 Server 项目运行应用。

  2. 从地址栏复制 URL,打开另一个浏览器实例或选项卡,并在地址栏中粘贴该 URL。

  3. 选择任一浏览器,输入名称和消息,然后选择按钮发送消息。 两个页面上立即显示名称和消息:

    SignalRBlazor sample app open in two browser windows showing exchanged messages.

    引文:Star Trek VI: The Undiscovered Country ©1991 Paramount

创建 Blazor Server 应用

按照所选工具的指南进行操作:

注意

需要 Visual Studio 16.10 或更高版本以及 .NET Core SDK 5.0.0 或更高版本。

  1. 创建新项目。

  2. 选择“Blazor Server 应用”模板。 选择“下一步”。

  3. 在“项目名称”字段中键入 BlazorServerSignalRApp。 确认“位置”条目正确无误或为项目提供位置。 选择“下一步”。

  4. 选择“创建”。

添加 SignalR 客户端库

  1. 在“解决方案资源管理器”中,右键单击 BlazorServerSignalRApp 项目,然后选择“管理 NuGet 包” 。

  2. 在“管理 NuGet 包”对话框中,确认“包源”设置为“nuget.org” 。

  3. 选择“浏览”后,在搜索框中键入“Microsoft.AspNetCore.SignalR.Client”。

  4. 在搜索结果中,选择 Microsoft.AspNetCore.SignalR.Client 包。 将版本设置为与应用共享框架匹配的版本。 选择“安装” 。

  5. 如果出现“预览更改”对话框,则选择“确定”。

  6. 如果出现“许可证接受”对话框,如果你同意许可条款,请选择“我接受”。

添加 SignalR 集线器

创建 Hubs(复数)文件夹,并添加以下 ChatHub 类 (Hubs/ChatHub.cs):

using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;

namespace BlazorServerSignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

为 SignalR 中心添加服务和终结点

  1. 打开 Startup.cs 文件。

  2. Microsoft.AspNetCore.ResponseCompressionChatHub 类的命名空间添加到文件的顶部:

    using Microsoft.AspNetCore.ResponseCompression;
    using BlazorServerSignalRApp.Server.Hubs;
    
  3. 将响应压缩中间件服务添加到 Startup.ConfigureServices

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddSingleton<WeatherForecastService>();
        services.AddResponseCompression(opts =>
        {
            opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
                new[] { "application/octet-stream" });
        });
    }
    
  4. Startup.Configure中:

    • 使用处理管道的配置顶部的“响应压缩中间件”。
    • 在映射 Blazor 中心的终结点和客户端回退之间,为中心添加一个终结点。
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseResponseCompression();
    
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
        app.UseStaticFiles();
    
        app.UseRouting();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapBlazorHub();
            endpoints.MapHub<ChatHub>("/chathub");
            endpoints.MapFallbackToPage("/_Host");
        });
    }
    

添加用于聊天的 Razor 组件代码

  1. 打开 Pages/Index.razor 文件。

  2. 将标记替换为以下代码:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager NavigationManager
    @implements IAsyncDisposable
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection hubConnection;
        private List<string> messages = new List<string>();
        private string userInput;
        private string messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                InvokeAsync(StateHasChanged);
            });
    
            await hubConnection.StartAsync();
        }
    
        async Task Send() =>
            await hubConnection.SendAsync("SendMessage", userInput, messageInput);
    
        public bool IsConnected =>
            hubConnection.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            if (hubConnection is not null)
            {
                await hubConnection.DisposeAsync();
            }
        }
    }
    

运行应用

按照工具的指南进行操作:

  1. F5 来运行应用并进行调试,或者按 Ctrl+F5 (Windows)/+F5 (macOS) 来运行应用但不调试。

  2. 从地址栏复制 URL,打开另一个浏览器实例或选项卡,并在地址栏中粘贴该 URL。

  3. 选择任一浏览器,输入名称和消息,然后选择按钮发送消息。 两个页面上立即显示名称和消息:

    SignalRBlazor sample app open in two browser windows showing exchanged messages.

    引文:Star Trek VI: The Undiscovered Country ©1991 Paramount

后续步骤

在本教程中,你了解了如何执行以下操作:

  • 创建 Blazor 项目
  • 添加 SignalR 客户端库
  • 添加 SignalR 集线器
  • 添加 SignalR 服务和 SignalR 中心的终结点
  • 添加用于聊天的 Razor 组件代码

若要了解有关生成 Blazor 应用的详细信息,请参阅 Blazor 文档:

其他资源

了解如何:

  • 创建 Blazor 项目
  • 添加 SignalR 客户端库
  • 添加 SignalR 集线器
  • 添加 SignalR 服务和 SignalR 中心的终结点
  • 添加用于聊天的 Razor 组件代码

在本教程结束时,你将拥有一个正常运行的聊天应用。

先决条件

示例应用

本教程不需要下载教程的示例聊天应用。 示例应用是按照本教程的步骤生成的最终工作应用。

查看或下载示例代码

创建托管 Blazor WebAssembly 应用

按照所选工具的指南进行操作:

注意

需要 Visual Studio 16.6 或更高版本以及 .NET Core SDK 3.1.300 或更高版本。

  1. 创建新项目。

  2. 选择“Blazor WebAssembly 应用”模板。 选择“下一步”。

  3. 在“项目名称”字段中键入 BlazorWebAssemblySignalRApp。 确认“位置”条目正确无误或为项目提供位置。 选择“下一步”。

  4. 在“其他信息”对话框中,选中“托管的 ASP.NET Core”复选框。

  5. 选择“创建”。

添加 SignalR 客户端库

  1. 在“解决方案资源管理器”中,右键单击 BlazorWebAssemblySignalRApp.Client 项目,然后选择“管理 NuGet 包” 。

  2. 在“管理 NuGet 包”对话框中,确认“包源”设置为“nuget.org” 。

  3. 选择“浏览”后,在搜索框中键入“Microsoft.AspNetCore.SignalR.Client”。

  4. 在搜索结果中,选择 Microsoft.AspNetCore.SignalR.Client 包。 将版本设置为与应用共享框架匹配的版本。 选择“安装” 。

  5. 如果出现“预览更改”对话框,则选择“确定”。

  6. 如果出现“许可证接受”对话框,如果你同意许可条款,请选择“我接受”。

添加 SignalR 集线器

BlazorWebAssemblySignalRApp.Server 项目中,创建 Hubs(复数)文件夹,并添加以下 ChatHub 类 (Hubs/ChatHub.cs):

using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;

namespace BlazorWebAssemblySignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

为 SignalR 中心添加服务和终结点

  1. BlazorWebAssemblySignalRApp.Server 项目中打开 Startup.cs 文件。

  2. ChatHub 类的命名空间添加到文件顶部:

    using BlazorWebAssemblySignalRApp.Server.Hubs;
    
  3. 将 SignalR 和响应压缩中间件服务添加到 Startup.ConfigureServices

    services.AddSignalR();
    services.AddResponseCompression(opts =>
    {
        opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            new[] { "application/octet-stream" });
    });
    
  4. Startup.Configure中:

    • 使用处理管道的配置顶部的“响应压缩中间件”。
    • 在控制器终结点和客户端回退之间,为中心添加一个终结点。
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseResponseCompression();
    
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseWebAssemblyDebugging();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
        app.UseBlazorFrameworkFiles();
        app.UseStaticFiles();
    
        app.UseRouting();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapHub<ChatHub>("/chathub");
            endpoints.MapFallbackToFile("index.html");
        });
    }
    

添加用于聊天的 Razor 组件代码

  1. BlazorWebAssemblySignalRApp.Client 项目中打开 Pages/Index.razor 文件。

  2. 将标记替换为以下代码:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager NavigationManager
    @implements IDisposable
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection hubConnection;
        private List<string> messages = new List<string>();
        private string userInput;
        private string messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                StateHasChanged();
            });
    
            await hubConnection.StartAsync();
        }
    
        async Task Send() =>
            await hubConnection.SendAsync("SendMessage", userInput, messageInput);
    
        public bool IsConnected =>
            hubConnection.State == HubConnectionState.Connected;
    
        public void Dispose()
        {
            _ = hubConnection?.DisposeAsync();
        }
    }
    

运行应用

按照工具的指南进行操作:

  1. 在“解决方案资源管理器”中,选择 BlazorWebAssemblySignalRApp.Server 项目。 按 F5 来运行应用并进行调试,或者按 Ctrl+F5 (Windows)/+F5 (macOS) 来运行应用但不调试。

    重要

    执行托管的 Blazor WebAssembly 应用时,请从解决方案的 Server 项目运行应用。

  2. 从地址栏复制 URL,打开另一个浏览器实例或选项卡,并在地址栏中粘贴该 URL。

  3. 选择任一浏览器,输入名称和消息,然后选择按钮发送消息。 两个页面上立即显示名称和消息:

    SignalRBlazor sample app open in two browser windows showing exchanged messages.

    引文:Star Trek VI: The Undiscovered Country ©1991 Paramount

创建 Blazor Server 应用

按照所选工具的指南进行操作:

注意

需要 Visual Studio 16.6 或更高版本以及 .NET Core SDK 3.1.300 或更高版本。

  1. 创建新项目。

  2. 选择“Blazor Server 应用”模板。 选择“下一步”。

  3. 在“项目名称”字段中键入 BlazorServerSignalRApp。 确认“位置”条目正确无误或为项目提供位置。 选择“下一步”。

  4. 选择“创建”。

添加 SignalR 客户端库

  1. 在“解决方案资源管理器”中,右键单击 BlazorServerSignalRApp 项目,然后选择“管理 NuGet 包” 。

  2. 在“管理 NuGet 包”对话框中,确认“包源”设置为“nuget.org” 。

  3. 选择“浏览”后,在搜索框中键入“Microsoft.AspNetCore.SignalR.Client”。

  4. 在搜索结果中,选择 Microsoft.AspNetCore.SignalR.Client 包。 将版本设置为与应用共享框架匹配的版本。 选择“安装” 。

  5. 如果出现“预览更改”对话框,则选择“确定”。

  6. 如果出现“许可证接受”对话框,如果你同意许可条款,请选择“我接受”。

添加 System.Text.Encodings.Web 包

本部分仅适用于 ASP.NET Core 版本 3.x 的应用。

由于在 ASP.NET Core 3.x 应用中使用 System.Text.Json 5.x 时出现包解析问题,项目需要 System.Text.Encodings.Web 的包引用。 在未来的 .NET 5 修补程序版本中,将解决基础问题。 有关详细信息,请参阅 System.Text.Json 定义无依赖项的 netcoreapp3.0(dotnet/运行时 #45560)

若要将 System.Text.Encodings.Web 添加到项目,请按照所选工具的指南进行操作:

  1. 在“解决方案资源管理器”中,右键单击 BlazorServerSignalRApp 项目,然后选择“管理 NuGet 包” 。

  2. 在“管理 NuGet 包”对话框中,确认“包源”设置为“nuget.org” 。

  3. 选择“浏览”后,在搜索框中键入“System.Text.Encodings.Web”。

  4. 在搜索结果中,选择 System.Text.Encodings.Web 包。 选择与正在使用的共享框架相匹配的包版本。 选择“安装” 。

  5. 如果出现“预览更改”对话框,则选择“确定”。

  6. 如果出现“许可证接受”对话框,如果你同意许可条款,请选择“我接受”。

添加 SignalR 集线器

创建 Hubs(复数)文件夹,并添加以下 ChatHub 类 (Hubs/ChatHub.cs):

using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;

namespace BlazorServerSignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

为 SignalR 中心添加服务和终结点

  1. 打开 Startup.cs 文件。

  2. Microsoft.AspNetCore.ResponseCompressionChatHub 类的命名空间添加到文件的顶部:

    using Microsoft.AspNetCore.ResponseCompression;
    using BlazorServerSignalRApp.Server.Hubs;
    
  3. 将响应压缩中间件服务添加到 Startup.ConfigureServices

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddSingleton<WeatherForecastService>();
        services.AddResponseCompression(opts =>
        {
            opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
                new[] { "application/octet-stream" });
        });
    }
    
  4. Startup.Configure中:

    • 使用处理管道的配置顶部的“响应压缩中间件”。
    • 在映射 Blazor 中心的终结点和客户端回退之间,为中心添加一个终结点。
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseResponseCompression();
    
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
        app.UseStaticFiles();
    
        app.UseRouting();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapBlazorHub();
            endpoints.MapHub<ChatHub>("/chathub");
            endpoints.MapFallbackToPage("/_Host");
        });
    }
    

添加用于聊天的 Razor 组件代码

  1. 打开 Pages/Index.razor 文件。

  2. 将标记替换为以下代码:

    @page "/"
    @using Microsoft.AspNetCore.SignalR.Client
    @inject NavigationManager NavigationManager
    @implements IAsyncDisposable
    
    <div class="form-group">
        <label>
            User:
            <input @bind="userInput" />
        </label>
    </div>
    <div class="form-group">
        <label>
            Message:
            <input @bind="messageInput" size="50" />
        </label>
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection hubConnection;
        private List<string> messages = new List<string>();
        private string userInput;
        private string messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = $"{user}: {message}";
                messages.Add(encodedMsg);
                InvokeAsync(StateHasChanged);
            });
    
            await hubConnection.StartAsync();
        }
    
        async Task Send() =>
            await hubConnection.SendAsync("SendMessage", userInput, messageInput);
    
        public bool IsConnected =>
            hubConnection.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            await hubConnection?.DisposeAsync();
        }
    }
    

运行应用

按照工具的指南进行操作:

  1. F5 来运行应用并进行调试,或者按 Ctrl+F5 (Windows)/+F5 (macOS) 来运行应用但不调试。

  2. 从地址栏复制 URL,打开另一个浏览器实例或选项卡,并在地址栏中粘贴该 URL。

  3. 选择任一浏览器,输入名称和消息,然后选择按钮发送消息。 两个页面上立即显示名称和消息:

    SignalRBlazor sample app open in two browser windows showing exchanged messages.

    引文:Star Trek VI: The Undiscovered Country ©1991 Paramount

后续步骤

在本教程中,你了解了如何执行以下操作:

  • 创建 Blazor 项目
  • 添加 SignalR 客户端库
  • 添加 SignalR 集线器
  • 添加 SignalR 服务和 SignalR 中心的终结点
  • 添加用于聊天的 Razor 组件代码

若要了解有关生成 Blazor 应用的详细信息,请参阅 Blazor 文档:

其他资源