自动重新连接 Blazor 服务器端
原标题:Auto reconnect Blazor Serverside
Blazor serverside (dotnet core 3.1)
I run into the problem that on customer side this is shown:
Could not reconnect to the server. Reload the page to restore functionality.
Each time I update the code base or internet is broken or something like this.
Now the goal is that it should reload the page as soon as the server is back again (or in some interval).
Is there any possibility that could help me?
最佳回答
You can try this code:
问题回答
This will wait until the reload button appears and then will wait until the server is back up before actually reloading.
From https://github.com/dotnet/aspnetcore/issues/10325#issuecomment-537979717
From .NET 6 up you can use (still works in .NET 8):
This keeps all of the original startup process as is and just adds a page reload on connection down, without needing a mutations observer.
For .Net 8 (Base on SignalIR documentation)
App.Razor:
For example, if you have a Blazor Web app
Create boot.js on wwwroot (wwwroot/boot.js)
One way to determine the type of your Blazor project is to check the script tag that references the Blazor framework. If your project is a Blazor Web App, you will see a script tag with the src attribute set to _framework/blazor.web.js. This indicates that your Blazor app runs on the browser and uses WebAssembly to execute the .NET code.
boot.js content for a Blazor Web App:
(() => {
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({
circuit: {
reconnectionHandler: {
onConnectionDown: () => currentReconnectionProcess ??= startReconnectionProcess(),
onConnectionUp: () => {
currentReconnectionProcess?.cancel();
currentReconnectionProcess = null;
}
}
}
});
})();
boot.js content for a Blazor Server
(() => {
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;
}
}
});
})();
Create App.razor.css on Components folder (same folder of App.razor)
#reconnect-modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 100; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(255,255,255); /* Fallback color */
background-color: rgba(255,255,255,0.7); /* White w/ opacity */
color: #000000;
border: 1px solid #888;
padding-top: 27px;
font-size: 25px;
font-weight: bold;
text-align: center;
}
Here s an alternative but I m not sure it works 100%.
In .NET 8, defaultReconnectionHandler does not seem to be set up immediately after Blazor.start() returns. Once it is, _reconnectCallback can be set up.
my solution atm, thus, looks like this: looking till defaultReconnectionHandler is set up
disable the popup:
disable autostart:
own autostart boot code
this does the job for me atm
I am sure still many are facing the problem ("Could not reconnect to the server. Reload the page to restore functionality.") even on .Net 8 & none of the answers here are working. The only solutions is to stay plain. Just remove all these extra flavours and use the default. Even with boot.js from last 1-2 years now that s also not working. So stay simple, through that whenever you reopen the tab its autostart=true makes the call and restarts the connection.
By default autostart is true.
One trick some people forget about is that you can actually "watch" your code base for changes, if you open your favorite terminal and run dotnet run watch debug in the same folder as your cproj file it should watch your changes so when you refresh your browser it should pick up any changes to your application, formore information read: https://learn.microsoft.com/en-us/aspnet/core/tutorials/dotnet-watch?view=aspnetcore-3.1
dotnet watch is a tool that runs a .NET Core CLI command when source files change. For example, a file change can trigger compilation, test execution, or deployment.
Hope this helps