diff --git a/src/Aspire.Dashboard/Components/Controls/ApplicationName.razor.cs b/src/Aspire.Dashboard/Components/Controls/ApplicationName.razor.cs index f564e7fbb83..b66a4267065 100644 --- a/src/Aspire.Dashboard/Components/Controls/ApplicationName.razor.cs +++ b/src/Aspire.Dashboard/Components/Controls/ApplicationName.razor.cs @@ -31,11 +31,28 @@ protected override async Task OnInitializedAsync() if (DashboardClient.IsEnabled && !DashboardClient.WhenConnected.IsCompletedSuccessfully) { _disposalCts = new CancellationTokenSource(); - await DashboardClient.WhenConnected.WaitAsync(_disposalCts.Token); + try + { + await DashboardClient.WhenConnected.WaitAsync(_disposalCts.Token); + } + catch + { + // Ignore exceptions that occur during connection. Other code handles this error. + _pageTitle = GetApplicationName(); + } } } protected override void OnParametersSet() + { + var applicationName = GetApplicationName(); + + _pageTitle = string.IsNullOrEmpty(AdditionalText) + ? applicationName + : $"{applicationName} ({AdditionalText})"; + } + + private string GetApplicationName() { string applicationName; @@ -48,9 +65,7 @@ protected override void OnParametersSet() applicationName = DashboardClient.ApplicationName; } - _pageTitle = string.IsNullOrEmpty(AdditionalText) - ? applicationName - : $"{applicationName} ({AdditionalText})"; + return applicationName; } public void Dispose() diff --git a/src/Aspire.Dashboard/Components/Layout/MainLayout.razor.cs b/src/Aspire.Dashboard/Components/Layout/MainLayout.razor.cs index 4b18e713c67..51547e06d08 100644 --- a/src/Aspire.Dashboard/Components/Layout/MainLayout.razor.cs +++ b/src/Aspire.Dashboard/Components/Layout/MainLayout.razor.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using Aspire.Dashboard.Components.Dialogs; using Aspire.Dashboard.Components.Pages; using Aspire.Dashboard.Configuration; @@ -25,6 +26,7 @@ public partial class MainLayout : IGlobalKeydownListener, IAsyncDisposable private DotNetObjectReference? _shortcutManagerReference; private DotNetObjectReference? _layoutReference; private IDialogReference? _openPageDialog; + private CancellationTokenSource? _disposalCts; private const string SettingsDialogId = "SettingsDialog"; private const string HelpDialogId = "HelpDialog"; @@ -68,6 +70,9 @@ public partial class MainLayout : IGlobalKeydownListener, IAsyncDisposable [Inject] public required ILocalStorage LocalStorage { get; init; } + [Inject] + public required ILogger Logger { get; init; } + [CascadingParameter] public required ViewportInformation ViewportInformation { get; set; } @@ -100,6 +105,15 @@ protected override async Task OnInitializedAsync() return ValueTask.CompletedTask; }); } + else + { + if (!DashboardClient.WhenConnected.IsCompletedSuccessfully) + { + // Check if the dashboard client can connect. + // Run in a new task to not block other behavior if a connection error occurs and a dialog is shown. + _ = Task.Run(EnsureClientConnectionAsync); + } + } var result = await JS.InvokeAsync("window.getBrowserInfo"); TimeProvider.SetBrowserTimeZone(result.TimeZone); @@ -136,6 +150,44 @@ await MessageService.ShowMessageBarAsync(options => } } + private async Task EnsureClientConnectionAsync() + { + Debug.Assert(DashboardClient.IsEnabled, "Dashboard client must be enabled to ensure connection."); + + _disposalCts = new CancellationTokenSource(); + try + { + await DashboardClient.WhenConnected.WaitAsync(_disposalCts.Token); + } + catch (Exception ex) + { + Logger.LogError(ex, "Connection error."); + + var dialogParameters = new DialogParameters + { + PrimaryAction = DialogsLoc[nameof(Resources.Dialogs.ConnectionErrorDialogRetryButton)], + SecondaryAction = DialogsLoc[nameof(Resources.Dialogs.ConnectionErrorDialogCancelButton)], + PreventDismissOnOverlayClick = true, + Content = new MessageBoxContent + { + Title = DialogsLoc[nameof(Resources.Dialogs.ConnectionErrorDialogTitle)], + MarkupMessage = new MarkupString(DialogsLoc[nameof(Resources.Dialogs.ConnectionErrorDialogMessage)]), + Intent = MessageBoxIntent.Confirmation, + IconColor = Color.Error, + Icon = new Microsoft.FluentUI.AspNetCore.Components.Icons.Filled.Size24.DismissCircle() + } + }; + var reference = await DialogService.ShowMessageBoxAsync(dialogParameters); + + var result = await reference.Result; + if (!result.Cancelled) + { + // Force dashboard to reload. + NavigationManager.NavigateTo(DashboardUrls.ResourcesUrl(), forceLoad: true); + } + } + } + protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) @@ -280,6 +332,7 @@ private void CloseMobileNavMenu() public async ValueTask DisposeAsync() { + _disposalCts?.Cancel(); _shortcutManagerReference?.Dispose(); _layoutReference?.Dispose(); _themeChangedSubscription?.Dispose(); diff --git a/src/Aspire.Dashboard/Resources/Dialogs.Designer.cs b/src/Aspire.Dashboard/Resources/Dialogs.Designer.cs index c6fa7cbd1e4..1d795ab5093 100644 --- a/src/Aspire.Dashboard/Resources/Dialogs.Designer.cs +++ b/src/Aspire.Dashboard/Resources/Dialogs.Designer.cs @@ -60,6 +60,42 @@ internal Dialogs() { } } + /// + /// Looks up a localized string similar to Cancel. + /// + public static string ConnectionErrorDialogCancelButton { + get { + return ResourceManager.GetString("ConnectionErrorDialogCancelButton", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to connect to the app host. Please ensure the app host is running and try again.. + /// + public static string ConnectionErrorDialogMessage { + get { + return ResourceManager.GetString("ConnectionErrorDialogMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retry. + /// + public static string ConnectionErrorDialogRetryButton { + get { + return ResourceManager.GetString("ConnectionErrorDialogRetryButton", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection error. + /// + public static string ConnectionErrorDialogTitle { + get { + return ResourceManager.GetString("ConnectionErrorDialogTitle", resourceCulture); + } + } + /// /// Looks up a localized string similar to Close. /// diff --git a/src/Aspire.Dashboard/Resources/Dialogs.resx b/src/Aspire.Dashboard/Resources/Dialogs.resx index 65c74a75ef8..079eb7ae16d 100644 --- a/src/Aspire.Dashboard/Resources/Dialogs.resx +++ b/src/Aspire.Dashboard/Resources/Dialogs.resx @@ -304,4 +304,16 @@ Close + + Connection error + + + Unable to connect to the app host. Please ensure the app host is running and try again. + + + Retry + + + Cancel + \ No newline at end of file diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.cs.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.cs.xlf index cfedff51236..5fabf316882 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.cs.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.cs.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close Zavřít diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.de.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.de.xlf index 7e0c94bfb60..36a5d09baaa 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.de.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.de.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close Schließen diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.es.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.es.xlf index b478e25a7c8..e8755dd63b7 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.es.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.es.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close Cerrar diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.fr.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.fr.xlf index 160022ba135..9782d2c0b98 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.fr.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.fr.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close Fermer diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.it.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.it.xlf index cde31289088..1a8195570f0 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.it.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.it.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close Chiudi diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.ja.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.ja.xlf index 99fcb1970f7..ee4f3e8e5c1 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.ja.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.ja.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close 閉じる diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.ko.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.ko.xlf index effa069b862..c462d184560 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.ko.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.ko.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close 닫기 diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.pl.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.pl.xlf index 9d89c27bde3..d44f88ab69e 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.pl.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.pl.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close Zamknij diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.pt-BR.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.pt-BR.xlf index f71c735e474..44d1958ece5 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.pt-BR.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.pt-BR.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close Fechar diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.ru.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.ru.xlf index e47efce76f5..1d11e4a7100 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.ru.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.ru.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close Закрыть diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.tr.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.tr.xlf index d32b503addb..04251ce671a 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.tr.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.tr.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close Kapat diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.zh-Hans.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.zh-Hans.xlf index cce8e90d92b..a7d376bed4e 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.zh-Hans.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.zh-Hans.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close 关闭 diff --git a/src/Aspire.Dashboard/Resources/xlf/Dialogs.zh-Hant.xlf b/src/Aspire.Dashboard/Resources/xlf/Dialogs.zh-Hant.xlf index f00217e136f..89c18304374 100644 --- a/src/Aspire.Dashboard/Resources/xlf/Dialogs.zh-Hant.xlf +++ b/src/Aspire.Dashboard/Resources/xlf/Dialogs.zh-Hant.xlf @@ -2,6 +2,26 @@ + + Cancel + Cancel + + + + Unable to connect to the app host. Please ensure the app host is running and try again. + Unable to connect to the app host. Please ensure the app host is running and try again. + + + + Retry + Retry + + + + Connection error + Connection error + + Close 關閉