Blazor Server App 失去連線處置

情境: SignalR 失去連線, Could not reconnect to the server. Reload the page to restore functionality.

引言

Blazor Server App 偶而會失去連線出現如下訊息:

Could not reconnect to the server. Reload the page to restore functionality.
Reconnection failed. Try reloading the page if you're unable to reconnect.

大部份只是網路短暫跳針這時只要 retry 就行了。但是 Blazor Server App 預設的顯示方法太隱誨了。

經研究要嘛改寫預設的處置行為,要嘛讓隱誨變“顯現”。

參考文章

處理紀錄

經研究決定讓隱誨變“顯現”就好了。

若 Blazer Server App 失去連線,預設出現 <div id="components-reconnect-modal>...</div>

依不同的狀況錯誤訊息內容稍有不同。其也有相同的部份,要嘛用 <button/> 要嘛用 <a/> 讓使用者交互處理。只是 <button/><a/> 預設 CSS 太隱誨,我們讓它們“顯現”出來。

site.css
/****** 失去連線時處置 ******/
/* Wait until a 'reload' button appears */
#components-reconnect-modal h5 a {
  font-size: 1.25rem;
  padding: 4px 8px;
  color: var(--mud-palette-primary);
  text-decoration: underline
}

/* Wait until a 'reset' button appears */
#components-reconnect-modal button {
  font-size: 1.25rem;
  padding: 8px 16px;
  color: var(--mud-palette-primary-text);
  background-color: var(--mud-palette-primary);
  border: 2px solid var(--mud-palette-primary-darken);
  border-radius: 8px;
}

  #components-reconnect-modal button:hover {
    color: var(--mud-palette-primary);
    background-color: var(--mud-palette-primary-text);
  }
  
 /* xs,sm 行動模式下,把『失去連線處置訊息』移到營幕中間讓單手可以按到 Reload。 */
@media(max-width: 960px) {
  #components-reconnect-modal {
    display: flex !important;
    justify-content: center !important;
    align-items: center !important;
  }
}  

沒圖沒真象

讓隱晦的<a/>與<button/>顯現。


處理紀錄2:改寫預設的處置行為

找到二個改寫 #components-reconnect-modal 預設行為的文章,決定試一下以提昇 UX。

預設行為:SignalR 連線正常時不會出現,不正常會自動 append 到網頁最尾端。

#components-reconnect-modal預設行為狀態有四種,以分別用不同的 Css Class Name 顯示:

SS class
Indicates…

components-reconnect-hide

連線正常 An active connection is re-established to the server. Hide the modal.

components-reconnect-show

連線不正常-嘗試重新連線,可能是網路跳針有機會連回並接續操作。 A lost connection. The client is attempting to reconnect. Show the modal.

components-reconnect-failed

連線不正常-嘗試連線失敗,大概率連接不回來了。 Reconnection failed, probably due to a network failure. To attempt reconnection, call window.Blazor.reconnect() in JavaScript.

components-reconnect-rejected

連線不正常-無法連線,只能重新載入頁面。 Reconnection rejected. The server was reached but refused the connection, and the user's state on the server is lost. To reload the app, call location.reload() in JavaScript. This connection state may result when:

  • A crash in the server-side circuit occurs.

  • The client is disconnected long enough for the server to drop the user's state. Instances of the user's components are disposed.

  • The server is restarted, or the app's worker process is recycled.

也就是正常 SignalR 連線狀態時,

<div id="components-reconnect-modal" class="components-reconnect-hide">
    There was a problem with the connection!
</div>

不正常連線狀態時,Blazor 引擎會為 #components-reconnect-modal加上不正常狀態的 Css Class Name 。

<div id="components-reconnect-modal" class="components-reconnect-show">
    There was a problem with the connection!
</div>

<!-- 或 -->
<div id="components-reconnect-modal" class="components-reconnect-failed">
    There was a problem with the connection!
</div>

<!-- 或 -->
<div id="components-reconnect-modal" class="components-reconnect-rejected">
    There was a problem with the connection!
</div>

簡化連線不正常操作

我們直接簡化連線不正常操作成一種就好,紀錄如下:

預設行為:SignalR 連線正常時不會出現,不正常會自動 append 到網頁最尾端。

改寫行為時,要自訂 #components-reconnect-modal 呈現內容,Blazor 引擎會為 #components-reconnect-modal加上不正常狀態的 Css Class Name 。我們只要用 CSS 控制當 Signal R 連線不正常時再讓它顯現就好,平常就隱身。

_Layout.cshtml _Host.cshtml 加入 #components-reconnect-modal,會

_Layout.cshtml
@using Microsoft.AspNetCore.Components.Web
@namespace YourProject.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPE html>
<html lang="zh-hant">
<head>
  ...略...
</head>
<body>
  @RenderBody()

  @* 客製化:SignalR 失去連線處置 *@
  <div id="components-reconnect-modal">
    <p>與伺服器連線出現問題!(嘗試連線:<span id="components-reconnect-current-attempt"></span> / <span id="components-reconnect-max-retries"></span>)</p>
    <button onclick="location.reload()">直接刷新頁面</button>
  </div>

  <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>

  <script src="_framework/blazor.server.js"></script>
  <script src="_content/MudBlazor/MudBlazor.min.js"></script>
</body>
</html>

wwwroot\site.css
/****** 客製化:SignalR 失去連線處置:Could not reconnect to the server. Reload the page to restore functionality. ******/
#components-reconnect-modal {
  display: none; /* ----- SignalR 連線正常時不顯現 */
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1050;
  overflow: hidden;
  background-color: #fff;
  opacity: 0.8;
  font-weight: bold;
}

  #components-reconnect-modal.components-reconnect-show,
  #components-reconnect-modal.components-reconnect-failed,
  #components-reconnect-modal.components-reconnect-rejected {
    display: flex; /* ------ SignalR 連線不正常時顯現 */
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }

  /* Wait until a 'reload' button appears */
  #components-reconnect-modal p {
    font-size: 1.25rem;
  }

  /* Wait until a 'reload' button appears */
  #components-reconnect-modal a
  {
    font-size: 1.25rem;
    padding: 4px 8px;
    color: var(--mud-palette-primary);
    text-decoration: underline
  }

  /* Wait until a 'reset' button appears */
  #components-reconnect-modal button {
    font-size: 1.25rem;
    padding: 8px 16px;
    color: var(--mud-palette-primary-text);
    background-color: var(--mud-palette-primary);
    border: 2px solid var(--mud-palette-primary-darken);
    border-radius: 8px;
  }

    #components-reconnect-modal button:hover {
      color: var(--mud-palette-primary);
      background-color: var(--mud-palette-primary-text);
    }

沒圖沒真象2

自訂 SignalR 連線不正常操作:置中並明確顯現。

自訂 SignalR 連線不正常操作:置中並明確顯現。

(EOF)

Last updated