ASP.NET Core BlazorSignalR 指南 您所在的位置:网站首页 reconnetionhandler ASP.NET Core BlazorSignalR 指南

ASP.NET Core BlazorSignalR 指南

2023-04-22 00:30| 来源: 网络整理| 查看: 265

ASP.NET Core BlazorSignalR 指南 项目 04/06/2023

注意

此版本不是本文的最新版本。 若要切换到最新版本,请使用目录顶部的 ASP.NET Core 版本选择器。

如果选择器在较窄的浏览器窗口中不可见,请扩大窗口或选择垂直省略号 (⋮) >“目录”。

本文介绍如何配置和管理 Blazor 应用中的 SignalR 连接。

有关 ASP.NET Core SignalR 配置的常规指南,请参阅文档的 ASP.NET Core SignalR 概述区域中的主题。 若要配置已添加到托管 Blazor WebAssembly 应用的 SignalR(例如,在将 ASP.NET Core SignalR 与 Blazor 配合使用教程中这样做),或者要配置一个使用 SignalR 的独立 Blazor WebAssembly 应用,请参阅 ASP.NET Core SignalR 配置。

禁用热重载的响应压缩

使用热重载时,请在 Development 环境中禁用响应压缩中间件。 以下示例使用从 Blazor 项目模板创建的项目中的现有环境检查。 无论是否使用项目模板中的默认代码,始终首先在请求处理管道中调用 UseResponseCompression。

在 Blazor Server 应用的 Program.cs 中:

if (!app.Environment.IsDevelopment()) { app.UseResponseCompression(); app.UseExceptionHandler("/Error"); app.UseHsts(); }

托管的 Blazor WebAssembly 解决方案中 Client 项目的 Program.cs 中:

if (app.Environment.IsDevelopment()) { app.UseWebAssemblyDebugging(); } else { app.UseResponseCompression(); app.UseExceptionHandler("/Error"); app.UseHsts(); } 用于身份验证的 SignalR 跨源协商 (Blazor WebAssembly)

若要将 SignalR 的基础客户端配置为发送凭据(如 cookie 或 HTTP 身份验证标头),请执行以下操作:

使用 SetBrowserRequestCredentials 在跨源 fetch 请求中设置 Include。

IncludeRequestCredentialsMessageHandler.cs:

using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.WebAssembly.Http; public class IncludeRequestCredentialsMessageHandler : DelegatingHandler { protected override Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include); return base.SendAsync(request, cancellationToken); } }

在构建中心连接的位置,将 HttpMessageHandler 分配给 HttpMessageHandlerFactory 选项:

private HubConnectionBuilder? hubConnection; ... hubConnection = new HubConnectionBuilder() .WithUrl(new Uri(Navigation.ToAbsoluteUri("/chathub")), options => { options.HttpMessageHandlerFactory = innerHandler => new IncludeRequestCredentialsMessageHandler { InnerHandler = innerHandler }; }).Build();

上面的示例将中心连接 URL 配置为绝对 URI 地址 /chathub,这是 SignalR 与 Blazor 教程中用于 Index 组件 (Pages/Index.razor) 的 URL。 该 URI 也可以通过字符串来设置,例如 https://signalr.example.com,或者通过配置进行设置。 Navigation 是一个注入的 NavigationManager。

有关详细信息,请参阅 ASP.NET Core SignalR 配置。

呈现模式 (Blazor WebAssembly)

如果使用 SignalR 的 Blazor WebAssembly 应用配置为在服务器上预呈现,则预呈现会在客户端与服务器建立连接之前发生。 有关详细信息,请参阅以下文章:

ASP.NET Core 中的组件标记帮助程序 预呈现和集成 ASP.NET Core Razor 组件 Blazor WebAssembly 应用的其他资源 托管 Blazor WebAssembly:保护 SignalR 中心 托管和部署 ASP.NET Core Blazor WebAssembly ASP.NET Core SignalR 概述 ASP.NET Core SignalR 配置 Blazor 示例 GitHub 存储库 (dotnet/blazor-samples) 为 webfarm 托管使用粘滞会话 (Blazor Server)

Blazor Server 应用预呈现以响应第一个客户端请求,这会在服务器上创建 UI 状态。 客户端尝试创建 SignalR 连接时,“必须重新连接到同一服务器”。 使用多个后端服务器的 Blazor Server 应用应实现粘滞会话,从而建立 SignalR 连接。

注意

未在 webfarm 中启用粘滞会话的应用引发以下错误:

blazor.server.js:1 Uncaught (in promise) 错误:由于基础连接已关闭,调用被取消。

Azure SignalR 服务 (Blazor Server)

我们建议将 Azure SignalR 服务用于 Microsoft Azure 中托管的 Blazor Server 应用。 该服务与应用的 Blazor 中心配合使用,以便将 Blazor Server 应用扩展到大量并发 SignalR 连接。 此外,SignalR 服务的全球覆盖和高性能数据中心可帮助显著减少由于地理位置造成的延迟。

可将服务的 ServerStickyMode 选项或配置值设置为 Required,从而为 Azure SignalR 服务启用粘滞会话。 有关详细信息,请参阅托管和部署 ASP.NET Core Blazor Server。

Blazor Server 应用的线路处理程序选项

使用下表所示的 CircuitOptions 配置 Blazor Server 线路。

选项 默认 说明 DetailedErrors false 当线路上发生未经处理的异常时,或者通过 JS 互操作的 .NET 方法调用导致异常时,便向 JavaScript 发送详细的异常消息。 DisconnectedCircuitMaxRetained 100 服务器在内存中一次保留的断开连接的线路数上限。 DisconnectedCircuitRetentionPeriod 3 分钟 断开连接的线路被移除前在内存中保留的最长时间。 JSInteropDefaultCallTimeout 1 分钟 服务器在使异步 JavaScript 函数调用超时之前等待的最长时间。 MaxBufferedUnacknowledgedRenderBatches 10 在给定时间内,服务器在内存中对每条线路保留用以支持重新连接可靠的未确认的呈现批处理的最大数量。 达到限制后,服务器会停止生成新的呈现批处理,直到客户端确认了一个或多个批处理。

使用 AddServerSideBlazor 的选项委托配置 Program.cs 中的选项。 下面的示例将分配上表中显示的默认选项值。 确认 Program.cs 使用 System 命名空间 (using System;)。

在 Program.cs中:

builder.Services.AddServerSideBlazor(options => { options.DetailedErrors = false; options.DisconnectedCircuitMaxRetained = 100; options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromMinutes(3); options.JSInteropDefaultCallTimeout = TimeSpan.FromMinutes(1); options.MaxBufferedUnacknowledgedRenderBatches = 10; });

若要配置 HubConnectionContext,请结合使用 HubConnectionContextOptions 和 AddHubOptions。 有关选项说明,请参阅 ASP.NET Core SignalR 配置。 以下示例分配默认选项值。 确认 Program.cs 使用 System 命名空间 (using System;)。

在 Program.cs中:

builder.Services.AddServerSideBlazor() .AddHubOptions(options => { options.ClientTimeoutInterval = TimeSpan.FromSeconds(30); options.EnableDetailedErrors = false; options.HandshakeTimeout = TimeSpan.FromSeconds(15); options.KeepAliveInterval = TimeSpan.FromSeconds(15); options.MaximumParallelInvocationsPerClient = 1; options.MaximumReceiveMessageSize = 32 * 1024; options.StreamBufferCapacity = 10; });

警告

MaximumReceiveMessageSize 的默认值为 32 KB。 提高此值可能会增加拒绝服务(DoS) 攻击风险。

有关 Blazor Server 的内存模型的信息,请参阅托管和部署 ASP.NET Core Blazor Server。

Blazor 中心终结点路由配置 (Blazor Server)

在 Program.cs 中,Blazor Server 应用调用 MapBlazorHub 以将 BlazorHub 映射到应用的默认路径。 Blazor Server 脚本 (blazor.server.js) 自动指向 MapBlazorHub 创建的终结点。

反映 UI 中的连接状态 (Blazor Server)

如果客户端检测到连接已丢失,在客户端尝试重新连接时会向用户显示默认 UI。 如果重新连接失败,则会向用户提供重试选项。

若要自定义 UI,请定义一个 id 为 components-reconnect-modal 的元素。 以下示例将元素放置在主机页中。

Pages/_Host.cshtml:

There was a problem with the connection!

注意

如果应用呈现了多个 id 为 components-reconnect-modal 的元素,则只有第一个呈现的元素会接收 CSS 类更改以显示或隐藏元素。

将以下 CSS 样式添加到站点的样式表中。

wwwroot/css/site.css:

#components-reconnect-modal { display: none; } #components-reconnect-modal.components-reconnect-show, #components-reconnect-modal.components-reconnect-failed, #components-reconnect-modal.components-reconnect-rejected { display: block; }

下表介绍了 Blazor 框架应用于 components-reconnect-modal 元素的 CSS 类。

CSS 类 指示… components-reconnect-show 连接已丢失。 客户端正在尝试重新连接。 显示模式。 components-reconnect-hide 将为服务器重新建立活动连接。 隐藏模式。 components-reconnect-failed 重新连接失败,可能是由于网络故障引起的。 若要尝试重新连接,请在 JavaScript 中调用 window.Blazor.reconnect()。 components-reconnect-rejected 已拒绝重新连接。 已达到服务器,但拒绝连接,服务器上的用户状态丢失。 若要重新加载应用,请在 JavaScript 中调用 location.reload()。 当出现以下情况时,可能会导致此连接状态:服务器端线路发生故障。客户端断开连接的时间足以使服务器删除用户的状态。 用户组件的实例已被处置。服务器已重启,或者应用的工作进程被回收。

通过在站点的 CSS 中为模式元素设置 transition-delay 属性,自定义重新连接显示出现之前的延迟。 以下示例将转换延迟从 500 毫秒(默认值)设置为 1000 毫秒(1 秒)。

wwwroot/css/site.css:

#components-reconnect-modal { transition: visibility 0s linear 1000ms; }

若要显示当前的重新连接尝试,请定义一个 id 为 components-reconnect-current-attempt 的元素。 若要显示最大重新连接重试次数,请定义一个 id 为 components-reconnect-max-retries 的元素。 以下示例按照上一个示例,将这些元素放置在主机页的重新连接尝试模式元素内。

Pages/_Host.cshtml:

There was a problem with the connection! (Current reconnect attempt: / )

出现自定义重新连接模式时,它会根据前面的代码呈现如下所示的内容:

There was a problem with the connection! (Current reconnect attempt: 3 / 8) 呈现模式 (Blazor Server)

默认情况下,Blazor Server 应用会在客户端与服务器建立连接之前在服务器上预呈现用户界面。 有关详细信息,请参阅 ASP.NET Core 中的组件标记帮助程序。

Blazor 启动

在 Pages/_Host.cshtml 文件 (Blazor Server) 或 wwwroot/index.html(实现了 SignalR 的托管 Blazor WebAssembly)中配置 Blazor 应用的 SignalR 回路的手动启动:

将 autostart="false" 属性添加到 blazor.{server|webassembly}.js 脚本的 标记中。 放置一个在加载 Blazor 脚本后调用 Blazor.start() 的脚本,将其置于结束的 标记内。

禁用 autostart 时,应用中不依赖该回路的任何方面都能正常工作。 例如,客户端路由正常运行。 但是,在调用 Blazor.start() 之前,依赖于该回路的任何方面不会正常运行。 如果没有已建立的回路,应用行为是不可预测的。 例如,在回路断开连接时,组件方法无法执行。

有关详细信息,包括如何在文档准备就绪时初始化 Blazor,以及如何链接到 JS Promise,请参阅 ASP.NET Core Blazor 启动。

在客户端上配置 SignalR 超时和 Keep-Alive

为客户端配置以下值:

serverTimeoutInMilliseconds:服务器超时(以毫秒为单位)。 如果此超时已过但未从服务器接收任何消息,连接将终止并出现错误。 默认超时值为 30 秒。 服务器超时应至少是分配给 Keep-Alive 间隔 (keepAliveIntervalInMilliseconds) 的值的两倍。 keepAliveIntervalInMilliseconds:ping 服务器时采用的默认间隔。 使用此设置,服务器可以检测强行断开连接的情况,例如客户断开其计算机的网络连接。 此 ping 的发生频率最多与服务器 ping 的频率一样。 如果服务器每 5 秒 ping 一次,则分配的值低于 5000(5 秒)时,将会每 5 秒 ping 一次。 默认值为 15 秒。 Keep-Alive 间隔应小于或等于分配给服务器超时 (serverTimeoutInMilliseconds) 的值的一半。

针对 Pages/_Host.cshtml (Blazor Server) 或 wwwroot/index.html (Blazor WebAssembly) 的以下示例使用默认值:

Blazor.start({ configureSignalR: function (builder) { let c = builder.build(); c.serverTimeoutInMilliseconds = 30000; c.keepAliveIntervalInMilliseconds = 15000; builder.build = () => { return c; }; } });

在前面的标记中,{HOSTING MODEL} 占位符是 server(适用于 Blazor Server 应用)或 webassembly(适用于 Blazor WebAssembly 应用)。

在组件中创建中心连接时,在生成的 HubConnection 上设置 ServerTimeout(默认值:30 秒)、HandshakeTimeout(默认值:15 秒)和 KeepAliveInterval(默认值:15 秒)。 基于结合使用 SignalR 和 Blazor 教程中的 Index 组件的以下示例使用了默认值:

protected override async Task OnInitializedAsync() { hubConnection = new HubConnectionBuilder() .WithUrl(Navigation.ToAbsoluteUri("/chathub")) .Build(); hubConnection.ServerTimeout = TimeSpan.FromSeconds(30); hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(15); hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(15); hubConnection.On("ReceiveMessage", (user, message) => ... await hubConnection.StartAsync(); }

更改服务器超时 (ServerTimeout) 或 Keep-Alive 间隔 (KeepAliveInterval) 的值时:

服务器超时应至少是分配给 Keep-Alive 间隔的值的两倍。 Keep-Alive 间隔应小于或等于分配给服务器超时的值的一半。

有关详细信息,请参阅以下文章的“全球部署和连接失败”部分:

托管和部署 ASP.NET Core Blazor Server 托管和部署 ASP.NET Core Blazor WebAssembly 修改重新连接处理程序 (Blazor Server)

可以针对自定义行为修改重新连接处理程序的线路连接事件,如:

在连接断开时通知用户。 在线路连接时(通过客户端)执行日志记录。

若要修改连接事件,请为以下连接更改注册回调:

使用 onConnectionDown 删除的连接。 已建立/重新建立的连接使用 onConnectionUp。

必须同时指定 onConnectionDown 和 onConnectionUp。

Pages/_Host.cshtml:

... Blazor.start({ reconnectionHandler: { onConnectionDown: (options, error) => console.error(error), onConnectionUp: () => console.log("Up, up, and away!") } }); 重新连接失败后自动刷新页面 (Blazor Server)

默认的重新连接行为需要用户在重新连接失败后手动刷新页面。 但可使用自定义重新连接处理程序自动刷新页面:

Pages/_Host.cshtml:

...

wwwroot/boot.js:

(() => { const maximumRetryCount = 3; const retryIntervalMilliseconds = 5000; const reconnectModal = document.getElementById('reconnect-modal'); const startReconnectionProcess = () => { reconnectModal.style.display = 'block'; let isCanceled = false; (async () => { for (let i = 0; i < maximumRetryCount; i++) { reconnectModal.innerText = `Attempting to reconnect: ${i + 1} of ${maximumRetryCount}`; await new Promise(resolve => setTimeout(resolve, retryIntervalMilliseconds)); if (isCanceled) { return; } try { const result = await Blazor.reconnect(); if (!result) { // The server was reached, but the connection was rejected; reload the page. location.reload(); return; } // Successfully reconnected to the server. return; } catch { // Didn't reach the server; try again. } } // Retried too many times; reload the page. location.reload(); })(); return { cancel: () => { isCanceled = true; reconnectModal.style.display = 'none'; }, }; }; let currentReconnectionProcess = null; Blazor.start({ reconnectionHandler: { onConnectionDown: () => currentReconnectionProcess ??= startReconnectionProcess(), onConnectionUp: () => { currentReconnectionProcess?.cancel(); currentReconnectionProcess = null; }, }, }); })();

有关 Blazor 启动的详细信息,请参阅 ASP.NET Core Blazor 启动。

调整重新连接重试计数和间隔 (Blazor Server)

若要调整重新连接重试次数和间隔,请设置重试次数 (maxRetries) 和允许每次重试运行的毫秒数 (retryIntervalMilliseconds)。

Pages/_Host.cshtml:

... Blazor.start({ reconnectionOptions: { maxRetries: 3, retryIntervalMilliseconds: 2000 } });

有关 Blazor 启动的详细信息,请参阅 ASP.NET Core Blazor 启动。

从客户端断开 Blazor 线路连接 (Blazor Server)

默认情况下,触发 unload 页面事件时,Blazor 线路会断开连接。 若要断开客户端上其他方案的线路连接,请在相应的事件处理程序中调用 Blazor.disconnect。 在下面的示例中,当页面隐藏(pagehide 事件)时,线路会断开连接:

window.addEventListener('pagehide', () => { Blazor.disconnect(); });

有关 Blazor 启动的详细信息,请参阅 ASP.NET Core Blazor 启动。

Blazor Server 线路处理程序

Blazor Server 允许代码定义线路处理程序,后者允许在用户线路的状态发生更改时运行代码。 线路处理程序通过从 CircuitHandler 派生并在应用的服务容器中注册该类实现。 以下线路处理程序示例跟踪打开的 SignalR 连接。

TrackingCircuitHandler.cs:

using Microsoft.AspNetCore.Components.Server.Circuits; public class TrackingCircuitHandler : CircuitHandler { private HashSet circuits = new(); public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken) { circuits.Add(circuit); return Task.CompletedTask; } public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken) { circuits.Remove(circuit); return Task.CompletedTask; } public int ConnectedCircuits => circuits.Count; }

线路处理程序使用 DI 注册。 每个线路实例都会创建区分范围的实例。 借助前面示例中的 TrackingCircuitHandler 创建单一实例服务,因为必须跟踪所有线路的状态。

在 Program.cs中:

builder.Services.AddSingleton();

如果自定义线路处理程序的方法引发未处理异常,则该异常会导致 Blazor Server 线路产生严重错误。 若要容忍处理程序代码或被调用方法中的异常,请使用错误处理和日志记录将代码包装到一个或多个 try-catch 语句中。

当线路因用户断开连接而结束且框架正在清除线路状态时,框架会处置线路的 DI 范围。 处置范围时会处置所有实现 System.IDisposable 的区分线路范围的 DI 服务。 如果有任何 DI 服务在处置期间引发未处理异常,则框架会记录该异常。 有关详细信息,请参阅 ASP.NET Core Blazor 依赖项注入。

有关 ASP.NET Core SignalR 配置的常规指南,请参阅文档的 ASP.NET Core SignalR 概述区域中的主题。 若要配置已添加到托管 Blazor WebAssembly 应用的 SignalR(例如,在将 ASP.NET Core SignalR 与 Blazor 配合使用教程中这样做),或者要配置一个使用 SignalR 的独立 Blazor WebAssembly 应用,请参阅 ASP.NET Core SignalR 配置。

禁用热重载的响应压缩

使用热重载时,请在 Development 环境中禁用响应压缩中间件。 以下示例使用从 Blazor 项目模板创建的项目中的现有环境检查。 无论是否使用项目模板中的默认代码,始终首先在请求处理管道中调用 UseResponseCompression。

在 Blazor Server 应用的 Program.cs 中:

if (!app.Environment.IsDevelopment()) { app.UseResponseCompression(); app.UseExceptionHandler("/Error"); app.UseHsts(); }

托管的 Blazor WebAssembly 解决方案中 Client 项目的 Program.cs 中:

if (app.Environment.IsDevelopment()) { app.UseWebAssemblyDebugging(); } else { app.UseResponseCompression(); app.UseExceptionHandler("/Error"); app.UseHsts(); } 用于身份验证的 SignalR 跨源协商 (Blazor WebAssembly)

若要将 SignalR 的基础客户端配置为发送凭据(如 cookie 或 HTTP 身份验证标头),请执行以下操作:

使用 SetBrowserRequestCredentials 在跨源 fetch 请求中设置 Include。

IncludeRequestCredentialsMessageHandler.cs:

using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.WebAssembly.Http; public class IncludeRequestCredentialsMessageHandler : DelegatingHandler { protected override Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include); return base.SendAsync(request, cancellationToken); } }

在构建中心连接的位置,将 HttpMessageHandler 分配给 HttpMessageHandlerFactory 选项:

private HubConnectionBuilder? hubConnection; ... hubConnection = new HubConnectionBuilder() .WithUrl(new Uri(Navigation.ToAbsoluteUri("/chathub")), options => { options.HttpMessageHandlerFactory = innerHandler => new IncludeRequestCredentialsMessageHandler { InnerHandler = innerHandler }; }).Build();

上面的示例将中心连接 URL 配置为绝对 URI 地址 /chathub,这是 SignalR 与 Blazor 教程中用于 Index 组件 (Pages/Index.razor) 的 URL。 该 URI 也可以通过字符串来设置,例如 https://signalr.example.com,或者通过配置进行设置。 Navigation 是一个注入的 NavigationManager。

注意

若要对 SignalR 中心的用户进行身份验证,请参阅安全 ASP.NET Core Blazor WebAssembly。

有关详细信息,请参阅 ASP.NET Core SignalR 配置。

呈现模式 (Blazor WebAssembly)

如果使用 SignalR 的 Blazor WebAssembly 应用配置为在服务器上预呈现,则预呈现会在客户端与服务器建立连接之前发生。 有关详细信息,请参阅以下文章:

ASP.NET Core 中的组件标记帮助程序 预呈现和集成 ASP.NET Core Razor 组件 Blazor WebAssembly 应用的其他资源 托管 Blazor WebAssembly:保护 SignalR 中心 托管和部署 ASP.NET Core Blazor WebAssembly ASP.NET Core SignalR 概述 ASP.NET Core SignalR 配置 Blazor 示例 GitHub 存储库 (dotnet/blazor-samples) 为 webfarm 托管使用粘滞会话 (Blazor Server)

Blazor Server 应用预呈现以响应第一个客户端请求,这会在服务器上创建 UI 状态。 客户端尝试创建 SignalR 连接时,“必须重新连接到同一服务器”。 使用多个后端服务器的 Blazor Server 应用应实现粘滞会话,从而建立 SignalR 连接。

注意

未在 webfarm 中启用粘滞会话的应用引发以下错误:

blazor.server.js:1 Uncaught (in promise) 错误:由于基础连接已关闭,调用被取消。

Azure SignalR 服务 (Blazor Server)

我们建议将 Azure SignalR 服务用于 Microsoft Azure 中托管的 Blazor Server 应用。 该服务与应用的 Blazor 中心配合使用,以便将 Blazor Server 应用扩展到大量并发 SignalR 连接。 此外,SignalR 服务的全球覆盖和高性能数据中心可帮助显著减少由于地理位置造成的延迟。

可将服务的 ServerStickyMode 选项或配置值设置为 Required,从而为 Azure SignalR 服务启用粘滞会话。 有关详细信息,请参阅托管和部署 ASP.NET Core Blazor Server。

Blazor Server 应用的线路处理程序选项

使用下表所示的 CircuitOptions 配置 Blazor Server 线路。

选项 默认 说明 DetailedErrors false 当线路上发生未经处理的异常时,或者通过 JS 互操作的 .NET 方法调用导致异常时,便向 JavaScript 发送详细的异常消息。 DisconnectedCircuitMaxRetained 100 服务器在内存中一次保留的断开连接的线路数上限。 DisconnectedCircuitRetentionPeriod 3 分钟 断开连接的线路被移除前在内存中保留的最长时间。 JSInteropDefaultCallTimeout 1 分钟 服务器在使异步 JavaScript 函数调用超时之前等待的最长时间。 MaxBufferedUnacknowledgedRenderBatches 10 在给定时间内,服务器在内存中对每条线路保留用以支持重新连接可靠的未确认的呈现批处理的最大数量。 达到限制后,服务器会停止生成新的呈现批处理,直到客户端确认了一个或多个批处理。

使用 AddServerSideBlazor 的选项委托配置 Program.cs 中的选项。 下面的示例将分配上表中显示的默认选项值。 确认 Program.cs 使用 System 命名空间 (using System;)。

在 Program.cs中:

builder.Services.AddServerSideBlazor(options => { options.DetailedErrors = false; options.DisconnectedCircuitMaxRetained = 100; options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromMinutes(3); options.JSInteropDefaultCallTimeout = TimeSpan.FromMinutes(1); options.MaxBufferedUnacknowledgedRenderBatches = 10; });

若要配置 HubConnectionContext,请结合使用 HubConnectionContextOptions 和 AddHubOptions。 有关选项说明,请参阅 ASP.NET Core SignalR 配置。 以下示例分配默认选项值。 确认 Program.cs 使用 System 命名空间 (using System;)。

在 Program.cs中:

builder.Services.AddServerSideBlazor() .AddHubOptions(options => { options.ClientTimeoutInterval = TimeSpan.FromSeconds(30); options.EnableDetailedErrors = false; options.HandshakeTimeout = TimeSpan.FromSeconds(15); options.KeepAliveInterval = TimeSpan.FromSeconds(15); options.MaximumParallelInvocationsPerClient = 1; options.MaximumReceiveMessageSize = 32 * 1024; options.StreamBufferCapacity = 10; });

警告

MaximumReceiveMessageSize 的默认值为 32 KB。 提高此值可能会增加拒绝服务(DoS) 攻击风险。

有关 Blazor Server 的内存模型的信息,请参阅托管和部署 ASP.NET Core Blazor Server。

Blazor 中心终结点路由配置 (Blazor Server)

在 Program.cs 中,Blazor Server 应用调用 MapBlazorHub 以将 BlazorHub 映射到应用的默认路径。 Blazor Server 脚本 (blazor.server.js) 自动指向 MapBlazorHub 创建的终结点。

反映 UI 中的连接状态 (Blazor Server)

如果客户端检测到连接已丢失,在客户端尝试重新连接时会向用户显示默认 UI。 如果重新连接失败,则会向用户提供重试选项。

若要自定义 UI,请定义一个 id 为 components-reconnect-modal 的元素。 以下示例将元素放置在布局页中。

Pages/_Layout.cshtml:

There was a problem with the connection!

注意

如果应用呈现了多个 id 为 components-reconnect-modal 的元素,则只有第一个呈现的元素会接收 CSS 类更改以显示或隐藏元素。

将以下 CSS 样式添加到站点的样式表中。

wwwroot/css/site.css:

#components-reconnect-modal { display: none; } #components-reconnect-modal.components-reconnect-show, #components-reconnect-modal.components-reconnect-failed, #components-reconnect-modal.components-reconnect-rejected { display: block; }

下表介绍了 Blazor 框架应用于 components-reconnect-modal 元素的 CSS 类。

CSS 类 指示… components-reconnect-show 连接已丢失。 客户端正在尝试重新连接。 显示模式。 components-reconnect-hide 将为服务器重新建立活动连接。 隐藏模式。 components-reconnect-failed 重新连接失败,可能是由于网络故障引起的。 若要尝试重新连接,请在 JavaScript 中调用 window.Blazor.reconnect()。 components-reconnect-rejected 已拒绝重新连接。 已达到服务器,但拒绝连接,服务器上的用户状态丢失。 若要重新加载应用,请在 JavaScript 中调用 location.reload()。 当出现以下情况时,可能会导致此连接状态:服务器端线路发生故障。客户端断开连接的时间足以使服务器删除用户的状态。 用户组件的实例已被处置。服务器已重启,或者应用的工作进程被回收。

通过在站点的 CSS 中为模式元素设置 transition-delay 属性,自定义重新连接显示出现之前的延迟。 以下示例将转换延迟从 500 毫秒(默认值)设置为 1000 毫秒(1 秒)。

wwwroot/css/site.css:

#components-reconnect-modal { transition: visibility 0s linear 1000ms; }

若要显示当前的重新连接尝试,请定义一个 id 为 components-reconnect-current-attempt 的元素。 若要显示最大重新连接重试次数,请定义一个 id 为 components-reconnect-max-retries 的元素。 以下示例按照上一个示例,将这些元素放置在布局页的重新连接尝试模式元素内。

Pages/_Layout.cshtml:

There was a problem with the connection! (Current reconnect attempt: / )

出现自定义重新连接模式时,它会根据前面的代码呈现如下所示的内容:

There was a problem with the connection! (Current reconnect attempt: 3 / 8) 呈现模式 (Blazor Server)

默认情况下,Blazor Server 应用会在客户端与服务器建立连接之前在服务器上预呈现用户界面。 有关详细信息,请参阅 ASP.NET Core 中的组件标记帮助程序。

Blazor 启动

在 Pages/_Layout.cshtml 文件 (Blazor Server) 或 wwwroot/index.html(实现了 SignalR 的托管 Blazor WebAssembly)中配置 Blazor 应用的 SignalR 回路的手动启动:

将 autostart="false" 属性添加到 blazor.{server|webassembly}.js 脚本的 标记中。 放置一个在加载 Blazor 脚本后调用 Blazor.start() 的脚本,将其置于结束的 标记内。

禁用 autostart 时,应用中不依赖该回路的任何方面都能正常工作。 例如,客户端路由正常运行。 但是,在调用 Blazor.start() 之前,依赖于该回路的任何方面不会正常运行。 如果没有已建立的回路,应用行为是不可预测的。 例如,在回路断开连接时,组件方法无法执行。

有关详细信息,包括如何在文档准备就绪时初始化 Blazor,以及如何链接到 JS Promise,请参阅 ASP.NET Core Blazor 启动。

在客户端上配置 SignalR 服务器超时和 Keep-Alive Blazor Server 中心

本部分仅适用于 Blazor Server。

为客户端上的 Blazor Server 中心连接配置以下值:

serverTimeoutInMilliseconds:服务器超时(以毫秒为单位)。 如果此超时已过但未从服务器接收任何消息,连接将终止并出现错误。 默认超时值为 30 秒。 服务器超时应至少是分配给 Keep-Alive 间隔 (keepAliveIntervalInMilliseconds) 的值的两倍。 keepAliveIntervalInMilliseconds:ping 服务器时采用的默认间隔。 使用此设置,服务器可以检测强行断开连接的情况,例如客户断开其计算机的网络连接。 此 ping 的发生频率最多与服务器 ping 的频率一样。 如果服务器每 5 秒 ping 一次,则分配的值低于 5000(5 秒)时,将会每 5 秒 ping 一次。 默认值为 15 秒。 Keep-Alive 间隔应小于或等于分配给服务器超时 (serverTimeoutInMilliseconds) 的值的一半。

针对 Pages/_Layout.cshtml (Blazor Server) 或 wwwroot/index.html (Blazor WebAssembly) 的以下示例使用默认值:

Blazor.start({ configureSignalR: function (builder) { let c = builder.build(); c.serverTimeoutInMilliseconds = 30000; c.keepAliveIntervalInMilliseconds = 15000; builder.build = () => { return c; }; } }); 在 Razor 组件中创建的中心连接

本部分仅适用于 Blazor Server 组件和托管 Blazor WebAssembly 解决方案的 Client 项目中的组件。

在组件中创建中心连接时,在生成的 HubConnection 上设置 ServerTimeout(默认值:30 秒)、HandshakeTimeout(默认值:15 秒)和 KeepAliveInterval(默认值:15 秒)。 基于结合使用 SignalR 和 Blazor 教程中的 Index 组件的以下示例使用了默认值:

protected override async Task OnInitializedAsync() { hubConnection = new HubConnectionBuilder() .WithUrl(Navigation.ToAbsoluteUri("/chathub")) .Build(); hubConnection.ServerTimeout = TimeSpan.FromSeconds(30); hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(15); hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(15); hubConnection.On("ReceiveMessage", (user, message) => ... await hubConnection.StartAsync(); }

更改服务器超时 (ServerTimeout) 或 Keep-Alive 间隔 (KeepAliveInterval) 的值时:

服务器超时应至少是分配给 Keep-Alive 间隔的值的两倍。 Keep-Alive 间隔应小于或等于分配给服务器超时的值的一半。

有关详细信息,请参阅以下文章的“全球部署和连接失败”部分:

托管和部署 ASP.NET Core Blazor Server 托管和部署 ASP.NET Core Blazor WebAssembly 修改重新连接处理程序 (Blazor Server)

可以针对自定义行为修改重新连接处理程序的线路连接事件,如:

在连接断开时通知用户。 在线路连接时(通过客户端)执行日志记录。

若要修改连接事件,请为以下连接更改注册回调:

使用 onConnectionDown 删除的连接。 已建立/重新建立的连接使用 onConnectionUp。

必须同时指定 onConnectionDown 和 onConnectionUp。

Pages/_Layout.cshtml:

... Blazor.start({ reconnectionHandler: { onConnectionDown: (options, error) => console.error(error), onConnectionUp: () => console.log("Up, up, and away!") } });

有关 Blazor 启动的详细信息,请参阅 ASP.NET Core Blazor 启动。

调整重新连接重试计数和间隔 (Blazor Server)

若要调整重新连接重试次数和间隔,请设置重试次数 (maxRetries) 和允许每次重试运行的毫秒数 (retryIntervalMilliseconds)。

Pages/_Layout.cshtml:

... Blazor.start({ reconnectionOptions: { maxRetries: 3, retryIntervalMilliseconds: 2000 } });

有关 Blazor 启动的详细信息,请参阅 ASP.NET Core Blazor 启动。

从客户端断开 Blazor 线路连接 (Blazor Server)

默认情况下,触发 unload 页面事件时,Blazor 线路会断开连接。 若要断开客户端上其他方案的线路连接,请在相应的事件处理程序中调用 Blazor.disconnect。 在下面的示例中,当页面隐藏(pagehide 事件)时,线路会断开连接:

window.addEventListener('pagehide', () => { Blazor.disconnect(); });

有关 Blazor 启动的详细信息,请参阅 ASP.NET Core Blazor 启动。

Blazor Server 线路处理程序

Blazor Server 允许代码定义线路处理程序,后者允许在用户线路的状态发生更改时运行代码。 线路处理程序通过从 CircuitHandler 派生并在应用的服务容器中注册该类实现。 以下线路处理程序示例跟踪打开的 SignalR 连接。

TrackingCircuitHandler.cs:

using Microsoft.AspNetCore.Components.Server.Circuits; public class TrackingCircuitHandler : CircuitHandler { private HashSet circuits = new(); public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken) { circuits.Add(circuit); return Task.CompletedTask; } public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken) { circuits.Remove(circuit); return Task.CompletedTask; } public int ConnectedCircuits => circuits.Count; }

线路处理程序使用 DI 注册。 每个线路实例都会创建区分范围的实例。 借助前面示例中的 TrackingCircuitHandler 创建单一实例服务,因为必须跟踪所有线路的状态。

在 Program.cs中:

builder.Services.AddSingleton();

如果自定义线路处理程序的方法引发未处理异常,则该异常会导致 Blazor Server 线路产生严重错误。 若要容忍处理程序代码或被调用方法中的异常,请使用错误处理和日志记录将代码包装到一个或多个 try-catch 语句中。

当线路因用户断开连接而结束且框架正在清除线路状态时,框架会处置线路的 DI 范围。 处置范围时会处置所有实现 System.IDisposable 的区分线路范围的 DI 服务。 如果有任何 DI 服务在处置期间引发未处理异常,则框架会记录该异常。 有关详细信息,请参阅 ASP.NET Core Blazor 依赖项注入。

有关 ASP.NET Core SignalR 配置的常规指南,请参阅文档的 ASP.NET Core SignalR 概述区域中的主题。 若要配置已添加到托管 Blazor WebAssembly 应用的 SignalR(例如,在将 ASP.NET Core SignalR 与 Blazor 配合使用教程中这样做),或者要配置一个使用 SignalR 的独立 Blazor WebAssembly 应用,请参阅 ASP.NET Core SignalR 配置。

用于身份验证的 SignalR 跨源协商 (Blazor WebAssembly)

若要将 SignalR 的基础客户端配置为发送凭据(如 cookie 或 HTTP 身份验证标头),请执行以下操作:

使用 SetBrowserRequestCredentials 在跨源 fetch 请求中设置 Include。

IncludeRequestCredentialsMessageHandler.cs:

using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.WebAssembly.Http; public class IncludeRequestCredentialsMessageHandler : DelegatingHandler { protected override Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include); return base.SendAsync(request, cancellationToken); } }

在构建中心连接的位置,将 HttpMessageHandler 分配给 HttpMessageHandlerFactory 选项:

HubConnectionBuilder hubConnection; ... hubConnection = new HubConnectionBuilder() .WithUrl(new Uri(Navigation.ToAbsoluteUri("/chathub")), options => { options.HttpMessageHandlerFactory = innerHandler => new IncludeRequestCredentialsMessageHandler { InnerHandler = innerHandler }; }).Build();

上面的示例将中心连接 URL 配置为绝对 URI 地址 /chathub,这是 SignalR 与 Blazor 教程中用于 Index 组件 (Pages/Index.razor) 的 URL。 该 URI 也可以通过字符串来设置,例如 https://signalr.example.com,或者通过配置进行设置。 Navigation 是一个注入的 NavigationManager。

注意

若要对 SignalR 中心的用户进行身份验证,请参阅安全 ASP.NET Core Blazor WebAssembly。

有关详细信息,请参阅 ASP.NET Core SignalR 配置。

呈现模式 (Blazor WebAssembly)

如果使用 SignalR 的 Blazor WebAssembly 应用配置为在服务器上预呈现,则预呈现会在客户端与服务器建立连接之前发生。 有关详细信息,请参阅以下文章:

ASP.NET Core 中的组件标记帮助程序 预呈现和集成 ASP.NET Core Razor 组件 Blazor WebAssembly 应用的其他资源 托管 Blazor WebAssembly:保护 SignalR 中心 ASP.NET Core SignalR 概述 ASP.NET Core SignalR 配置 Blazor 示例 GitHub 存储库 (dotnet/blazor-samples) 为 webfarm 托管使用粘滞会话 (Blazor Server)

Blazor Server 应用预呈现以响应第一个客户端请求,这会在服务器上创建 UI 状态。 客户端尝试创建 SignalR 连接时,“必须重新连接到同一服务器”。 使用多个后端服务器的 Blazor Server 应用应实现粘滞会话,从而建立 SignalR 连接。

注意

未在 webfarm 中启用粘滞会话的应用引发以下错误:

blazor.server.js:1 Uncaught (in promise) 错误:由于基础连接已关闭,调用被取消。

Azure SignalR 服务 (Blazor Server)

我们建议将 Azure SignalR 服务用于 Microsoft Azure 中托管的 Blazor Server 应用。 该服务与应用的 Blazor 中心配合使用,以便将 Blazor Server 应用扩展到大量并发 SignalR 连接。 此外,SignalR 服务的全球覆盖和高性能数据中心可帮助显著减少由于地理位置造成的延迟。

如需对 Azure SignalR 服务的预呈现支持,请将应用配置为使用粘滞会话。 有关详细信息,请参阅托管和部署 ASP.NET Core Blazor Server。

Blazor Server 应用的线路处理程序选项

使用下表所示的 CircuitOptions 配置 Blazor Server 线路。

选项 默认 说明 DetailedErrors false 当线路上发生未经处理的异常时,或者通过 JS 互操作的 .NET 方法调用导致异常时,便向 JavaScript 发送详细的异常消息。 DisconnectedCircuitMaxRetained 100 服务器在内存中一次保留的断开连接的线路数上限。 DisconnectedCircuitRetentionPeriod 3 分钟 断开连接的线路被移除前在内存中保留的最长时间。 JSInteropDefaultCallTimeout 1 分钟 服务器在使异步 JavaScript 函数调用超时之前等待的最长时间。 MaxBufferedUnacknowledgedRenderBatches 10 在给定时间内,服务器在内存中对每条线路保留用以支持重新连接可靠的未确认的呈现批处理的最大数量。 达到限制后,服务器会停止生成新的呈现批处理,直到客户端确认了一个或多个批处理。

使用 AddServerSideBlazor 的选项委托配置 Startup.ConfigureServices 中的选项。 下面的示例将分配上表中显示的默认选项值。 确认 Startup.cs 使用 System 命名空间 (using System;)。

Startup.ConfigureServices:

services.AddServerSideBlazor(options => { options.DetailedErrors = false; options.DisconnectedCircuitMaxRetained = 100; options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromMinutes(3); options.JSInteropDefaultCallTimeout = TimeSpan.FromMinutes(1); options.MaxBufferedUnacknowledgedRenderBatches = 10; });

若要配置 HubConnectionContext,请结合使用 HubConnectionContextOptions 和 AddHubOptions。 有关选项说明,请参阅 ASP.NET Core SignalR 配置。 以下示例分配默认选项值。 确认 Startup.cs 使用 System 命名空间 (using System;)。

Startup.ConfigureServices:

services.AddServerSideBlazor() .AddHubOptions(options => { options.ClientTimeoutInterval = TimeSpan.FromSeconds(30); options.EnableDetailedErrors = false; options.HandshakeTimeout = TimeSpan.FromSeconds(15); options.KeepAliveInterval = TimeSpan.FromSeconds(15); options.MaximumParallelInvocationsPerClient = 1; options.MaximumReceiveMessageSize = 32 * 1024; options.StreamBufferCapacity = 10; });

警告

MaximumReceiveMessageSize 的默认值为 32 KB。 提高此值可能会增加拒绝服务(DoS) 攻击风险。

有关 Blazor Server 的内存模型的信息,请参阅托管和部署 ASP.NET Core Blazor Server。

Blazor 中心终结点路由配置 (Blazor Server)

在 Startup.Configure 中,Blazor Server 应用对 UseEndpoints 的 IEndpointRouteBuilder 调用 MapBlazorHub,以将 BlazorHub 映射到应用的默认路径。 Blazor Server 脚本 (blazor.server.js) 自动指向 MapBlazorHub 创建的终结点。

反映 UI 中的连接状态 (Blazor Server)

如果客户端检测到连接已丢失,在客户端尝试重新连接时会向用户显示默认 UI。 如果重新连接失败,则会向用户提供重试选项。

若要自定义 UI,请定义一个 id 为 components-reconnect-modal 的元素。 以下示例将元素放置在主机页中。

Pages/_Host.cshtml:

There was a problem with the connection!

注意

如果应用呈现了多个 id 为 components-reconnect-modal 的元素,则只有第一个呈现的元素会接收 CSS 类更改以显示或隐藏元素。

将以下 CSS 样式添加到站点的样式表中。

wwwroot/css/site.css:

#components-reconnect-modal { display: none; } #components-reconnect-modal.components-reconnect-show, #components-reconnect-modal.components-reconnect-failed, #components-reconnect-modal.components-reconnect-rejected { display: block; }

下表介绍了 Blazor 框架应用于 components-reconnect-modal 元素的 CSS 类。

CSS 类 指示… components-reconnect-show 连接已丢失。 客户端正在尝试重新连接。 显示模式。 components-reconnect-hide 将为服务器重新建立活动连接。 隐藏模式。 components-reconnect-failed 重新连接失败,可能是由于网络故障引起的。 若要尝试重新连接,请在 JavaScript 中调用 window.Blazor.reconnect()。 components-reconnect-rejected 已拒绝重新连接。 已达到服务器,但拒绝连接,服务器上的用户状态丢失。 若要重新加载应用,请在 JavaScript 中调用 location.reload()。 当出现以下情况时,可能会导致此连接状态:服务器端线路发生故障。客户端断开连接的时间足以使服务器删除用户的状态。 用户组件的实例已被处置。服务器已重启,或者应用的工作进程被回收。

通过在站点的 CSS 中为模式元素设置 transition-delay 属性,自定义重新连接显示出现之前的延迟。 以下示例将转换延迟从 500 毫秒(默认值)设置为 1000 毫秒(1 秒)。

wwwroot/css/site.css:

#components-reconnect-modal { transition: visibility 0s linear 1000ms; }

若要显示当前的重新连接尝试,请定义一个 id 为 components-reconnect-current-attempt 的元素。 若要显示最大重新连接重试次数,请定义一个 id 为 components-reconnect-max-retries 的元素。 以下示例按照上一个示例,将这些元素放置在主机页的重新连接尝试模式元素内。

Pages/_Host.cshtml:

There was a problem with the connection! (Current reconnect attempt: / )

出现自定义重新连接模式时,它会根据前面的代码呈现如下所示的内容:

There was a problem with the connection! (Current reconnect attempt: 3 / 8) 呈现模式 (Blazor Server)

默认情况下,Blazor Server 应用会在客户端与服务器建立连接之前在服务器上预呈现用户界面。 有关详细信息,请参阅 ASP.NET Core 中的组件标记帮助程序。

Blazor 启动

在 Pages/_Host.cshtml 文件 (Blazor Server) 或 wwwroot/index.html(实现了 SignalR 的托管 Blazor WebAssembly)中配置 Blazor 应用的 SignalR 回路的手动启动:

将 autostart="false" 属性添加到 blazor.{server|webassembly}.js 脚本的 标记中。 放置一个在加载 Blazor 脚本后调用 Blazor.start() 的脚本,将其置于结束的 标记内。

禁用 autostart 时,应用中不依赖该回路的任何方面都能正常工作。 例如,客户端路由正常运行。 但是,在调用 Blazor.start() 之前,依赖于该回路的任何方面不会正常运行。 如果没有已建立的回路,应用行为是不可预测的。 例如,在回路断开连接时,组件方法无法执行。

有关详细信息,包括如何在文档准备就绪时初始化 Blazor,以及如何链接到 JS Promise,请参阅 ASP.NET Core Blazor 启动。

在客户端上配置 SignalR 服务器超时和 Keep-Alive Blazor Server 中心

本部分仅适用于 Blazor Server。

为客户端上的 Blazor Server 中心连接配置以下值:

serverTimeoutInMilliseconds:服务器超时(以毫秒为单位)。 如果此超时已过但未从服务器接收任何消息,连接将终止并出现错误。 默认超时值为 30 秒。 服务器超时应至少是分配给 Keep-Alive 间隔 (keepAliveIntervalInMilliseconds) 的值的两倍。 keepAliveIntervalInMilliseconds:ping 服务器时采用的默认间隔。 使用此设置,服务器可以检测强行断开连接的情况,例如客户断开其计算机的网络连接。 此 ping 的发生频率最多与服务器 ping 的频率一样。 如果服务器每 5 秒 ping 一次,则分配的值低于 5000(5 秒)时,将会每 5 秒 ping 一次。 默认值为 15 秒。 Keep-Alive 间隔应小于或等于分配给服务器超时 (serverTimeoutInMilliseconds) 的值的一半。

针对 Pages/_Host.cshtml (Blazor Server) 或 wwwroot/index.html (Blazor WebAssembly) 的以下示例使用默认值:

Blazor.start({ configureSignalR: function (builder) { let c = builder.build(); c.serverTimeoutInMilliseconds = 30000; c.keepAliveIntervalInMilliseconds = 15000; builder.build = () => { return c; }; } }); 在 Razor 组件中创建的中心连接

本部分仅适用于 Blazor Server 组件和托管 Blazor WebAssembly 解决方案的 Client 项目中的组件。

在组件中创建中心连接时,在生成的 HubConnection 上设置 ServerTimeout(默认值:30 秒)、HandshakeTimeout(默认值:15 秒)和 KeepAliveInterval(默认值:15 秒)。 基于结合使用 SignalR 和 Blazor 教程中的 Index 组件的以下示例使用了默认值:

protected override async Task OnInitializedAsync() { hubConnection = new HubConnectionBuilder() .WithUrl(Navigation.ToAbsoluteUri("/chathub")) .Build(); hubConnection.ServerTimeout = TimeSpan.FromSeconds(30); hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(15); hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(15); hubConnection.On("ReceiveMessage", (user, message) => ... await hubConnection.StartAsync(); }

更改服务器超时 (ServerTimeout) 或 Keep-Alive 间隔 (KeepAliveInterval) 的值时:

服务器超时应至少是分配给 Keep-Alive 间隔的值的两倍。 Keep-Alive 间隔应小于或等于分配给服务器超时的值的一半。

有关详细信息,请参阅以下文章的“全球部署和连接失败”部分:

托管和部署 ASP.NET Core Blazor Server 托管和部署 ASP.NET Core Blazor WebAssembly 修改重新连接处理程序 (Blazor Server)

可以针对自定义行为修改重新连接处理程序的线路连接事件,如:

在连接断开时通知用户。 在线路连接时(通过客户端)执行日志记录。

若要修改连接事件,请为以下连接更改注册回调:

使用 onConnectionDown 删除的连接。 已建立/重新建立的连接使用 onConnectionUp。

必须同时指定 onConnectionDown 和 onConnectionUp。

Pages/_Host.cshtml:

... Blazor.start({ reconnectionHandler: { onConnectionDown: (options, error) => console.error(error), onConnectionUp: () => console.log("Up, up, and away!") } });

有关 Blazor 启动的详细信息,请参阅 ASP.NET Core Blazor 启动。

调整重新连接重试计数和间隔 (Blazor Server)

若要调整重新连接重试次数和间隔,请设置重试次数 (maxRetries) 和允许每次重试运行的毫秒数 (retryIntervalMilliseconds)。

Pages/_Host.cshtml:

... Blazor.start({ reconnectionOptions: { maxRetries: 3, retryIntervalMilliseconds: 2000 } });

有关 Blazor 启动的详细信息,请参阅 ASP.NET Core Blazor 启动。

从客户端断开 Blazor 线路连接 (Blazor Server)

默认情况下,触发 unload 页面事件时,Blazor 线路会断开连接。 若要断开客户端上其他方案的线路连接,请在相应的事件处理程序中调用 Blazor.disconnect。 在下面的示例中,当页面隐藏(pagehide 事件)时,线路会断开连接:

window.addEventListener('pagehide', () => { Blazor.disconnect(); });

有关 Blazor 启动的详细信息,请参阅 ASP.NET Core Blazor 启动。

Blazor Server 线路处理程序

Blazor Server 允许代码定义线路处理程序,后者允许在用户线路的状态发生更改时运行代码。 线路处理程序通过从 CircuitHandler 派生并在应用的服务容器中注册该类实现。 以下线路处理程序示例跟踪打开的 SignalR 连接。

TrackingCircuitHandler.cs:

using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Server.Circuits; public class TrackingCircuitHandler : CircuitHandler { private HashSet circuits = new(); public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken) { circuits.Add(circuit); return Task.CompletedTask; } public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken) { circuits.Remove(circuit); return Task.CompletedTask; } public int ConnectedCircuits => circuits.Count; }

线路处理程序使用 DI 注册。 每个线路实例都会创建区分范围的实例。 借助前面示例中的 TrackingCircuitHandler 创建单一实例服务,因为必须跟踪所有线路的状态。

Startup.cs:

public void ConfigureServices(IServiceCollection services) { ... services.AddSingleton(); }

如果自定义线路处理程序的方法引发未处理异常,则该异常会导致 Blazor Server 线路产生严重错误。 若要容忍处理程序代码或被调用方法中的异常,请使用错误处理和日志记录将代码包装到一个或多个 try-catch 语句中。

当线路因用户断开连接而结束且框架正在清除线路状态时,框架会处置线路的 DI 范围。 处置范围时会处置所有实现 System.IDisposable 的区分线路范围的 DI 服务。 如果有任何 DI 服务在处置期间引发未处理异常,则框架会记录该异常。 有关详细信息,请参阅 ASP.NET Core Blazor 依赖项注入。

有关 ASP.NET Core SignalR 配置的常规指南,请参阅文档的 ASP.NET Core SignalR 概述区域中的主题。 若要配置已添加到托管 Blazor WebAssembly 应用的 SignalR(例如,在将 ASP.NET Core SignalR 与 Blazor 配合使用教程中这样做),或者要配置一个使用 SignalR 的独立 Blazor WebAssembly 应用,请参阅 ASP.NET Core SignalR 配置。

用于身份验证的 SignalR 跨源协商 (Blazor WebAssembly)

若要将 SignalR 的基础客户端配置为发送凭据(如 cookie 或 HTTP 身份验证标头),请执行以下操作:

使用 SetBrowserRequestCredentials 在跨源 fetch 请求中设置 Include。

IncludeRequestCredentialsMessageHandler.cs:

using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.WebAssembly.Http; public class IncludeRequestCredentialsMessageHandler : DelegatingHandler { protected override Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include); return base.SendAsync(request, cancellationToken); } }

在构建中心连接的位置,将 HttpMessageHandler 分配给 HttpMessageHandlerFactory 选项:

HubConnectionBuilder hubConnection; ... hubConnection = new HubConnectionBuilder() .WithUrl(new Uri(Navigation.ToAbsoluteUri("/chathub")), options => { options.HttpMessageHandlerFactory = innerHandler => new IncludeRequestCredentialsMessageHandler { InnerHandler = innerHandler }; }).Build();

上面的示例将中心连接 URL 配置为绝对 URI 地址 /chathub,这是 SignalR 与 Blazor 教程中用于 Index 组件 (Pages/Index.razor) 的 URL。 该 URI 也可以通过字符串来设置,例如 https://signalr.example.com,或者通过配置进行设置。 Navigation 是一个注入的 NavigationManager。

注意

若要对 SignalR 中心的用户进行身份验证,请参阅安全 ASP.NET Core Blazor WebAssembly。

有关详细信息,请参阅 ASP.NET Core SignalR 配置。

Blazor WebAssembly 应用的其他资源 托管 Blazor WebAssembly:保护 SignalR 中心 ASP.NET Core SignalR 概述 ASP.NET Core SignalR 配置 Blazor 示例 GitHub 存储库 (dotnet/blazor-samples) 为 webfarm 托管使用粘滞会话 (Blazor Server)

Blazor Server 应用预呈现以响应第一个客户端请求,这会在服务器上创建 UI 状态。 客户端尝试创建 SignalR 连接时,“必须重新连接到同一服务器”。 使用多个后端服务器的 Blazor Server 应用应实现粘滞会话,从而建立 SignalR 连接。 有关详细信息,请参阅托管和部署 ASP.NET Core Blazor Server。

注意

未在 webfarm 中启用粘滞会话的应用引发以下错误:

blazor.server.js:1 Uncaught (in promise) 错误:由于基础连接已关闭,调用被取消。

Azure SignalR 服务 (Blazor Server)

我们建议将 Azure SignalR 服务用于 Microsoft Azure 中托管的 Blazor Server 应用。 该服务与应用的 Blazor 中心配合使用,以便将 Blazor Server 应用扩展到大量并发 SignalR 连接。 此外,SignalR 服务的全球覆盖和高性能数据中心可帮助显著减少由于地理位置造成的延迟。

如需对 Azure SignalR 服务的预呈现支持,请将应用配置为使用粘滞会话。 有关详细信息,请参阅托管和部署 ASP.NET Core Blazor Server。

Blazor Server 应用的线路处理程序选项

使用下表所示的 CircuitOptions 配置 Blazor Server 线路。

选项 默认 说明 DetailedErrors false 当线路上发生未经处理的异常时,或者通过 JS 互操作的 .NET 方法调用导致异常时,便向 JavaScript 发送详细的异常消息。 DisconnectedCircuitMaxRetained 100 服务器在内存中一次保留的断开连接的线路数上限。 DisconnectedCircuitRetentionPeriod 3 分钟 断开连接的线路被移除前在内存中保留的最长时间。 JSInteropDefaultCallTimeout 1 分钟 服务器在使异步 JavaScript 函数调用超时之前等待的最长时间。 MaxBufferedUnacknowledgedRenderBatches 10 在给定时间内,服务器在内存中对每条线路保留用以支持重新连接可靠的未确认的呈现批处理的最大数量。 达到限制后,服务器会停止生成新的呈现批处理,直到客户端确认了一个或多个批处理。

使用 AddServerSideBlazor 的选项委托配置 Startup.ConfigureServices 中的选项。 下面的示例将分配上表中显示的默认选项值。 确认 Startup.cs 使用 System 命名空间 (using System;)。

Startup.ConfigureServices:

services.AddServerSideBlazor(options => { options.DetailedErrors = false; options.DisconnectedCircuitMaxRetained = 100; options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromMinutes(3); options.JSInteropDefaultCallTimeout = TimeSpan.FromMinutes(1); options.MaxBufferedUnacknowledgedRenderBatches = 10; });

若要配置 HubConnectionContext,请结合使用 HubConnectionContextOptions 和 AddHubOptions。 有关选项说明,请参阅 ASP.NET Core SignalR 配置。 以下示例分配默认选项值。 确认 Startup.cs 使用 System 命名空间 (using System;)。

Startup.ConfigureServices:

services.AddServerSideBlazor() .AddHubOptions(options => { options.ClientTimeoutInterval = TimeSpan.FromSeconds(30); options.EnableDetailedErrors = false; options.HandshakeTimeout = TimeSpan.FromSeconds(15); options.KeepAliveInterval = TimeSpan.FromSeconds(15); options.MaximumParallelInvocationsPerClient = 1; options.MaximumReceiveMessageSize = 32 * 1024; options.StreamBufferCapacity = 10; });

警告

MaximumReceiveMessageSize 的默认值为 32 KB。 提高此值可能会增加拒绝服务(DoS) 攻击风险。

有关 Blazor Server 的内存模型的信息,请参阅托管和部署 ASP.NET Core Blazor Server。

Blazor 中心终结点路由配置 (Blazor Server)

在 Startup.Configure 中,Blazor Server 应用对 UseEndpoints 的 IEndpointRouteBuilder 调用 MapBlazorHub,以将 BlazorHub 映射到应用的默认路径。 Blazor Server 脚本 (blazor.server.js) 自动指向 MapBlazorHub 创建的终结点。

反映 UI 中的连接状态 (Blazor Server)

如果客户端检测到连接已丢失,在客户端尝试重新连接时会向用户显示默认 UI。 如果重新连接失败,则会向用户提供重试选项。

若要自定义 UI,请定义一个 id 为 components-reconnect-modal 的元素。 以下示例将元素放置在主机页中。

Pages/_Host.cshtml:

There was a problem with the connection!

注意

如果应用呈现了多个 id 为 components-reconnect-modal 的元素,则只有第一个呈现的元素会接收 CSS 类更改以显示或隐藏元素。

将以下 CSS 样式添加到站点的样式表中。

wwwroot/css/site.css:

#components-reconnect-modal { display: none; } #components-reconnect-modal.components-reconnect-show, #components-reconnect-modal.components-reconnect-failed, #components-reconnect-modal.components-reconnect-rejected { display: block; }

下表介绍了 Blazor 框架应用于 components-reconnect-modal 元素的 CSS 类。

CSS 类 指示… components-reconnect-show 连接已丢失。 客户端正在尝试重新连接。 显示模式。 components-reconnect-hide 将为服务器重新建立活动连接。 隐藏模式。 components-reconnect-failed 重新连接失败,可能是由于网络故障引起的。 若要尝试重新连接,请在 JavaScript 中调用 window.Blazor.reconnect()。 components-reconnect-rejected 已拒绝重新连接。 已达到服务器,但拒绝连接,服务器上的用户状态丢失。 若要重新加载应用,请在 JavaScript 中调用 location.reload()。 当出现以下情况时,可能会导致此连接状态:服务器端线路发生故障。客户端断开连接的时间足以使服务器删除用户的状态。 用户组件的实例已被处置。服务器已重启,或者应用的工作进程被回收。 呈现模式 (Blazor Server)

默认情况下,Blazor Server 应用会在客户端与服务器建立连接之前在服务器上预呈现用户界面。 有关详细信息,请参阅 ASP.NET Core 中的组件标记帮助程序。

Blazor 启动

在 Pages/_Host.cshtml 文件 (Blazor Server) 或 wwwroot/index.html(实现了 SignalR 的托管 Blazor WebAssembly)中配置 Blazor 应用的 SignalR 回路的手动启动:

将 autostart="false" 属性添加到 blazor.{server|webassembly}.js 脚本的 标记中。 放置一个在加载 Blazor 脚本后调用 Blazor.start() 的脚本,将其置于结束的 标记内。

禁用 autostart 时,应用中不依赖该回路的任何方面都能正常工作。 例如,客户端路由正常运行。 但是,在调用 Blazor.start() 之前,依赖于该回路的任何方面不会正常运行。 如果没有已建立的回路,应用行为是不可预测的。 例如,在回路断开连接时,组件方法无法执行。

有关详细信息,包括如何在文档准备就绪时初始化 Blazor,以及如何链接到 JS Promise,请参阅 ASP.NET Core Blazor 启动。

在客户端上配置 SignalR 服务器超时和 Keep-Alive Blazor Server 中心

本部分仅适用于 Blazor Server。

为客户端上的 Blazor Server 中心连接配置以下值:

serverTimeoutInMilliseconds:服务器超时(以毫秒为单位)。 如果此超时已过但未从服务器接收任何消息,连接将终止并出现错误。 默认超时值为 30 秒。 服务器超时应至少是分配给 Keep-Alive 间隔 (keepAliveIntervalInMilliseconds) 的值的两倍。 keepAliveIntervalInMilliseconds:ping 服务器时采用的默认间隔。 使用此设置,服务器可以检测强行断开连接的情况,例如客户断开其计算机的网络连接。 此 ping 的发生频率最多与服务器 ping 的频率一样。 如果服务器每 5 秒 ping 一次,则分配的值低于 5000(5 秒)时,将会每 5 秒 ping 一次。 默认值为 15 秒。 Keep-Alive 间隔应小于或等于分配给服务器超时 (serverTimeoutInMilliseconds) 的值的一半。

针对 Pages/_Host.cshtml (Blazor Server) 或 wwwroot/index.html (Blazor WebAssembly) 的以下示例使用默认值:

Blazor.start({ configureSignalR: function (builder) { let c = builder.build(); c.serverTimeoutInMilliseconds = 30000; c.keepAliveIntervalInMilliseconds = 15000; builder.build = () => { return c; }; } }); 在 Razor 组件中创建的中心连接

本部分仅适用于 Blazor Server 组件和托管 Blazor WebAssembly 解决方案的 Client 项目中的组件。

在组件中创建中心连接时,在生成的 HubConnection 上设置 ServerTimeout(默认值:30 秒)、HandshakeTimeout(默认值:15 秒)和 KeepAliveInterval(默认值:15 秒)。 基于结合使用 SignalR 和 Blazor 教程中的 Index 组件的以下示例使用了默认值:

protected override async Task OnInitializedAsync() { hubConnection = new HubConnectionBuilder() .WithUrl(Navigation.ToAbsoluteUri("/chathub")) .Build(); hubConnection.ServerTimeout = TimeSpan.FromSeconds(30); hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(15); hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(15); hubConnection.On("ReceiveMessage", (user, message) => ... await hubConnection.StartAsync(); }

更改服务器超时 (ServerTimeout) 或 Keep-Alive 间隔 (KeepAliveInterval) 的值时:

服务器超时应至少是分配给 Keep-Alive 间隔的值的两倍。 Keep-Alive 间隔应小于或等于分配给服务器超时的值的一半。

有关详细信息,请参阅以下文章的“全球部署和连接失败”部分:

托管和部署 ASP.NET Core Blazor Server 托管和部署 ASP.NET Core Blazor WebAssembly 修改重新连接处理程序 (Blazor Server)

可以针对自定义行为修改重新连接处理程序的线路连接事件,如:

在连接断开时通知用户。 在线路连接时(通过客户端)执行日志记录。

若要修改连接事件,请为以下连接更改注册回调:

使用 onConnectionDown 删除的连接。 已建立/重新建立的连接使用 onConnectionUp。

必须同时指定 onConnectionDown 和 onConnectionUp。

Pages/_Host.cshtml:

... Blazor.start({ reconnectionHandler: { onConnectionDown: (options, error) => console.error(error), onConnectionUp: () => console.log("Up, up, and away!") } });

有关 Blazor 启动的详细信息,请参阅 ASP.NET Core Blazor 启动。

调整重新连接重试计数和间隔 (Blazor Server)

若要调整重新连接重试次数和间隔,请设置重试次数 (maxRetries) 和允许每次重试运行的毫秒数 (retryIntervalMilliseconds)。

Pages/_Host.cshtml:

... Blazor.start({ reconnectionOptions: { maxRetries: 3, retryIntervalMilliseconds: 2000 } });

有关 Blazor 启动的详细信息,请参阅 ASP.NET Core Blazor 启动。

Blazor Server 线路处理程序

Blazor Server 允许代码定义线路处理程序,后者允许在用户线路的状态发生更改时运行代码。 线路处理程序通过从 CircuitHandler 派生并在应用的服务容器中注册该类实现。 以下线路处理程序示例跟踪打开的 SignalR 连接。

TrackingCircuitHandler.cs:

using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Server.Circuits; public class TrackingCircuitHandler : CircuitHandler { private HashSet circuits = new HashSet(); public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken) { circuits.Add(circuit); return Task.CompletedTask; } public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken) { circuits.Remove(circuit); return Task.CompletedTask; } public int ConnectedCircuits => circuits.Count; }

线路处理程序使用 DI 注册。 每个线路实例都会创建区分范围的实例。 借助前面示例中的 TrackingCircuitHandler 创建单一实例服务,因为必须跟踪所有线路的状态。

Startup.cs:

public void ConfigureServices(IServiceCollection services) { ... services.AddSingleton(); }

如果自定义线路处理程序的方法引发未处理异常,则该异常会导致 Blazor Server 线路产生严重错误。 若要容忍处理程序代码或被调用方法中的异常,请使用错误处理和日志记录将代码包装到一个或多个 try-catch 语句中。

当线路因用户断开连接而结束且框架正在清除线路状态时,框架会处置线路的 DI 范围。 处置范围时会处置所有实现 System.IDisposable 的区分线路范围的 DI 服务。 如果有任何 DI 服务在处置期间引发未处理异常,则框架会记录该异常。 有关详细信息,请参阅 ASP.NET Core Blazor 依赖项注入。

针对自定义服务用于捕获用户的 Blazor Server 线路处理程序

使用 CircuitHandler 从 AuthenticationStateProvider 捕获用户,并在服务中设置此用户。 有关详细信息和示例代码,请参阅 ASP.NET Core Blazor Server 其他安全方案。

避免在 Razor 组件中使用 IHttpContextAccessor/HttpContext

请勿在 Blazor Server 应用的 Razor 组件中直接或间接使用 IHttpContextAccessor/HttpContext。 Blazor 应用在 ASP.NET Core 管道上下文之外运行。 既不保证 HttpContext 在 IHttpContextAccessor 中可用,也不保证 HttpContext 会保留启动了 Blazor 应用的上下文。

建议在 Blazor 应用的初始呈现期间通过根组件参数将请求状态传递给此应用。 或者,应用可以将数据复制到根组件的初始化生命周期事件中的作用域内服务中,以便在整个应用中使用。 有关详细信息,请参阅 ASP.NET Core Blazor Server 其他安全方案。

Blazor Server 安全性的一个关键方面是,连接到给定线路的用户可能会在建立 Blazor 线路后的某个时间点得到更新,但不会更新 IHttpContextAccessor。 有关使用自定义服务应对此情况的详细信息,请参阅 ASP.NET Core Blazor Server 其他安全方案。

Blazor Server 应用的其他资源 Blazor Server 托管和部署指南:SignalR 配置 ASP.NET Core SignalR 概述 ASP.NET Core SignalR 配置 Blazor Server 安全文档 ASP.NET Core Blazor 身份验证和授权 保护 ASP.NET Core Blazor Server 应用 ASP.NET Core Blazor Server 的威胁缓解指南 ASP.NET Core Blazor Server 其他安全方案 Blazor Server 重新连接事件和组件生命周期事件 什么是 Azure SignalR 服务? Azure SignalR 服务的性能指南 将 ASP.NET Core SignalR 应用发布到 Azure 应用服务 Blazor 示例 GitHub 存储库 (dotnet/blazor-samples)


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有