我在 .NET 8 Blazor Server 中开发了一个应用程序(使用 SignalR 服务部署到 Azure)。用户经常开始在表单中输入一些信息(通常是相当多的信息),然后被拉到其他问题上,然后回来发现服务器已断开连接;屏幕呈灰色,屏幕顶部的消息为:“无法重新连接到服务器。重新加载页面以恢复功能”。断开连接所需的时间似乎是随机的。
客户端希望连接在上次 UI 活动后至少 2 小时内保持活动状态。我试过了:
有办法解决这个问题吗?或者,我们是否使用了错误的技术进行开发?
提前致谢。
以下代码可以解决下面截图中的
Could not reconnect to the server. Reload the page to restore functionality.
问题。我初步算了一下,大概需要10秒才能自动恢复。
这是我的测试代码
_主机.cshtml
@page "/"
@using Microsoft.AspNetCore.Components.Web
@namespace BlazorApp2.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link href="BlazorApp2.styles.css" rel="stylesheet" />
<link rel="icon" type="image/png" href="favicon.png"/>
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>
<body>
<component type="typeof(App)" render-mode="ServerPrerendered" />
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
@* autostart="false" here *@
<script src="_framework/blazor.server.js" autostart="false"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.0/signalr.min.js"></script>
<script>
// connect heartbeatHub
const connection = new signalR.HubConnectionBuilder()
.withUrl("/heartbeatHub")
.build();
connection.start().then(() => {
console.log("Connected to heartbeatHub");
setInterval(() => {
connection.invoke("SendHeartbeat")
.then(() => console.log("Heartbeat sent"))
.catch(err => console.error(err.toString()));
}, 5 * 60 * 1000); // Every 5 minutes will sent a Heartbeat
}).catch(err => console.error(err.toString()));
connection.on("HeartbeatReceived", (message) => {
console.log(`Server response: ${message}`);
});
connection.onclose(async () => {
console.log("Connection closed, retrying...");
await connection.start();
});
// For reconnecting the _blazor default hub
Blazor.start().then(() => {
Object.defineProperty(Blazor.defaultReconnectionHandler, '_reconnectionDisplay', {
get() {
return this.__reconnectionDisplay;
},
set(value) {
this.__reconnectionDisplay = {
show: () => value.show(),
update: (d) => value.update(d),
rejected: (d) => document.location.reload()
}
}
});
});
</script>
</body>
</html>
HeartbeatHub.cs
using Microsoft.AspNetCore.SignalR;
namespace BlazorApp2
{
public class HeartbeatHub : Hub
{
public async Task SendHeartbeat()
{
Console.WriteLine($"Received heartbeat from {Context.ConnectionId} at {DateTime.UtcNow}");
await Clients.Caller.SendAsync("HeartbeatReceived", "pong");
}
}
}
程序.cs
using BlazorApp2;
using BlazorApp2.Data;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
// [Optional] The second steps to check the size of your data in the form
builder.Services.AddServerSideBlazor().AddHubOptions(options =>
{
options.MaximumReceiveMessageSize = 1024 * 1024; // Set Size = 1MB
});
var app = builder.Build();
// Configure the HTTP request pipeline.
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();
// Register HeartbeatHub
app.MapHub<HeartbeatHub>("/heartbeatHub");
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();