Skip to content

Commit 3caba3c

Browse files
authored
108 add graceful unhandled exceptions in presentationblazor (#109)
* removed key vault * IsLocal() * Graceful error handling
1 parent a99c305 commit 3caba3c

File tree

9 files changed

+68
-69
lines changed

9 files changed

+68
-69
lines changed
Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,38 @@
11
@namespace Goodtocode.SemanticKernel.Presentation.Blazor.Components.Layout
22

33
@inherits LayoutComponentBase
4+
@inject NavigationManager Navigation
45

5-
<div class="page">
6-
<NavMenu />
6+
<NavMenu />
7+
<ErrorBoundary @ref="errorBoundaryRef">
8+
<ChildContent>
9+
<div class="page">
10+
<main>
11+
<article class="content">
12+
@Body
13+
</article>
14+
</main>
15+
</div>
16+
</ChildContent>
17+
<ErrorContent Context="ex">
18+
<div class="error-dialog-backdrop">
19+
<div class="error-dialog">
20+
<div class="alert alert-danger mb-3">
21+
Oops! Something went wrong.<br />
22+
@ex.Message
23+
</div>
24+
<button class="btn btn-sm btn-primary" @onclick="OnRecoverAndNavigate">Go Home</button>
25+
</div>
26+
</div>
27+
</ErrorContent>
28+
</ErrorBoundary>
729

8-
<main>
9-
<article class="content">
10-
@Body
11-
</article>
12-
</main>
13-
</div>
30+
@code {
31+
private ErrorBoundary? errorBoundaryRef;
1432

15-
<div id="blazor-error-ui" data-nosnippet>
16-
An unhandled error has occurred.
17-
<a href="." class="reload">Reload</a>
18-
<span class="dismiss">🗙</span>
19-
</div>
33+
private void OnRecoverAndNavigate()
34+
{
35+
errorBoundaryRef?.Recover();
36+
Navigation.NavigateTo("/", forceLoad: true);
37+
}
38+
}

src/Presentation.Blazor/Components/Layout/MainLayout.razor.css

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,25 @@ main {
1515
height: 100vh;
1616
}
1717

18-
#blazor-error-ui {
19-
color-scheme: light only;
20-
background: lightyellow;
21-
bottom: 0;
22-
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
23-
box-sizing: border-box;
24-
display: none;
25-
left: 0;
26-
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
18+
.error-dialog-backdrop {
2719
position: fixed;
28-
width: 100%;
29-
z-index: 1000;
20+
top: 10vh;
21+
left: 0;
22+
width: 100vw;
23+
height: 90vh;
24+
background: rgba(0,0,0,0.3);
25+
display: flex;
26+
align-items: center;
27+
justify-content: center;
28+
z-index: 1050;
3029
}
3130

32-
#blazor-error-ui .dismiss {
33-
cursor: pointer;
34-
position: absolute;
35-
right: 0.75rem;
36-
top: 0.5rem;
37-
}
31+
.error-dialog {
32+
background: #fff;
33+
border-radius: 8px;
34+
box-shadow: 0 4px 32px rgba(0,0,0,0.2);
35+
padding: 2rem 2.5rem;
36+
min-width: 320px;
37+
max-width: 90vw;
38+
text-align: center;
39+
}

src/Presentation.Blazor/ConfigureServices.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ namespace Goodtocode.SemanticKernel.Presentation.Blazor;
99

1010
public static class ConfigureServices
1111
{
12-
12+
public static bool IsLocal(this IWebHostEnvironment environment)
13+
{
14+
return environment.EnvironmentName.Equals("Local", StringComparison.OrdinalIgnoreCase);
15+
}
1316
public static void AddLocalEnvironment(this WebApplicationBuilder builder)
1417
{
1518
if (builder.Environment.IsEnvironment("Local"))

src/Presentation.Blazor/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
var app = builder.Build();
2424

25-
if (app.Environment.IsDevelopment() || app.Environment.EnvironmentName.Equals("Local", StringComparison.OrdinalIgnoreCase))
25+
if (app.Environment.IsDevelopment() || app.Environment.IsLocal())
2626
{
2727
app.UseDeveloperExceptionPage();
2828
}

src/Presentation.WebApi/ConfigureServices.cs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ namespace Goodtocode.SemanticKernel.Presentation.WebApi;
99
/// </summary>
1010
public static class ConfigureServices
1111
{
12+
/// <summary>
13+
/// Determines if the current environment is "Local".
14+
/// </summary>
15+
/// <param name="environment">The web host environment.</param>
16+
/// <returns>True if the environment is "Local"; otherwise, false.</returns>
17+
public static bool IsLocal(this IWebHostEnvironment environment)
18+
{
19+
return environment.EnvironmentName.Equals("Local", StringComparison.OrdinalIgnoreCase);
20+
}
21+
1222
/// <summary>
1323
/// Add Local Environment Configuration to mirror Development
1424
/// </summary>
@@ -31,17 +41,6 @@ public static void AddLocalEnvironment(this WebApplicationBuilder builder)
3141
/// <returns></returns>
3242
public static IServiceCollection AddWebUIServices(this IServiceCollection services)
3343
{
34-
//var assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version;
35-
//var majorVersion = $"v{assemblyVersion?.Major ?? 1}";
36-
//services.AddSwaggerGen(c =>
37-
//{
38-
// c.SwaggerDoc(majorVersion, new OpenApiInfo
39-
// {
40-
// Title = "Semantic Kernel Quick-start for WebAPI",
41-
// Version = majorVersion
42-
// });
43-
//});
44-
4544
services.AddControllersWithViews(setupAction =>
4645
{
4746
setupAction.Filters.Add(

src/Presentation.WebApi/Program.cs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
builder.Services.AddSemanticKernelOpenAIServices(builder.Configuration);
2727
builder.Services.AddWebUIServices();
2828
builder.Services.AddHealthChecks();
29-
//AddKeyVaultConfigurationSettings(builder);
3029
BuildApiVerAndApiExplorer(builder);
3130

3231
builder.Services.AddOpenTelemetry().UseAzureMonitor(options =>
@@ -36,7 +35,7 @@
3635

3736
var app = builder.Build();
3837

39-
if (app.Environment.IsDevelopment() || app.Environment.EnvironmentName.Equals("Local", StringComparison.OrdinalIgnoreCase))
38+
if (app.Environment.IsDevelopment() || app.Environment.IsLocal())
4039
{
4140
app.UseSwagger();
4241
UseSwaggerUiConfigs();
@@ -84,15 +83,4 @@ void BuildApiVerAndApiExplorer(WebApplicationBuilder webApplicationBuilder)
8483
setup.GroupNameFormat = "'v'VVV";
8584
setup.SubstituteApiVersionInUrl = true;
8685
});
87-
}
88-
89-
void AddKeyVaultConfigurationSettings(WebApplicationBuilder appBuilder)
90-
{
91-
if (!appBuilder.Configuration.GetValue<bool>("KeyVault:UseKeyVault")) return;
92-
93-
var azureKeyVaultEndpoint = appBuilder.Configuration["KeyVault:Endpoint"];
94-
if (azureKeyVaultEndpoint == null) return;
95-
var credential = new DefaultAzureCredential();
96-
var secretClient = new SecretClient(new Uri(azureKeyVaultEndpoint), credential);
97-
appBuilder.Configuration.AddAzureKeyVault(secretClient, new KeyVaultSecretManager());
98-
}
86+
}

src/Presentation.WebApi/appsettings.Development.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@
2828
"Scopes": "api.fullaccess",
2929
"SignUpSignInPolicyId": "B2C_1_susi"
3030
},
31-
"KeyVault": {
32-
"UseKeyVault": false,
33-
"Endpoint": "https://{{YOUR_KEYVAULT_NAME}}.vault.azure.net/"
34-
},
3531
"OpenAI": {
3632
"ChatCompletionModelId": "gpt-4.1-mini",
3733
"TextGenerationModelId": "gpt-3.5-turbo-instruct",

src/Presentation.WebApi/appsettings.Production.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@
2828
"Scopes": "api.fullaccess",
2929
"SignUpSignInPolicyId": "B2C_1_susi"
3030
},
31-
"KeyVault": {
32-
"UseKeyVault": false,
33-
"Endpoint": "https://{{YOUR_KEYVAULT_NAME}}.vault.azure.net/"
34-
},
3531
"OpenAI": {
3632
"ChatCompletionModelId": "gpt-4.1",
3733
"TextGenerationModelId": "gpt-3.5-turbo-instruct",

src/Presentation.WebApi/appsettings.local.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@
2828
"Scopes": "api.fullaccess",
2929
"SignUpSignInPolicyId": "B2C_1_susi"
3030
},
31-
"KeyVault": {
32-
"UseKeyVault": false,
33-
"Endpoint": "https://{{YOUR_KEYVAULT_NAME}}.vault.azure.net/"
34-
},
3531
"OpenAI": {
3632
"ChatCompletionModelId": "gpt-4.1-nano",
3733
"TextGenerationModelId": "gpt-3.5-turbo-instruct",

0 commit comments

Comments
 (0)