Skip to content

Commit af58537

Browse files
authored
feat(templates): improve server-side exception handling in Boilerplate bitfoundation#10196 (bitfoundation#10199)
1 parent ff488a9 commit af58537

File tree

8 files changed

+36
-7
lines changed

8 files changed

+36
-7
lines changed

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/Program.Services.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public static void ConfigureServices(this WebAssemblyHostBuilder builder)
3535
return httpClient;
3636
});
3737
services.AddKeyedScoped<HttpMessageHandler, HttpClientHandler>("PrimaryHttpMessageHandler");
38+
services.AddScoped<IExceptionHandler, WebClientExceptionHandler>();
3839

3940
services.AddTransient<IPrerenderStateService, WebClientPrerenderStateService>();
4041
}
@@ -45,8 +46,7 @@ public static void AddClientWebProjectServices(this IServiceCollection services,
4546
// The following services work both in blazor web assembly and server side for pre-rendering and blazor server.
4647

4748
services.AddScoped<IBitDeviceCoordinator, WebDeviceCoordinator>();
48-
services.AddScoped<IExceptionHandler, WebExceptionHandler>();
49-
services.AddScoped<IStorageService, BrowserStorageService>();
49+
services.AddScoped<IStorageService, WebStorageService>();
5050
//#if (notification == true)
5151
services.AddScoped<IPushNotificationService, WebPushNotificationService>();
5252
//#endif

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/Services/WebExceptionHandler.cs src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/Services/WebClientExceptionHandler.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace Boilerplate.Client.Web.Services;
22

3-
public partial class WebExceptionHandler : ClientExceptionHandlerBase
3+
public partial class WebClientExceptionHandler : ClientExceptionHandlerBase
44
{
55
protected override void Handle(Exception exception, ExceptionDisplayKind displayKind, Dictionary<string, object> parameters)
66
{

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/Services/BrowserStorageService.cs src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/Services/WebStorageService.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Boilerplate.Client.Web.Services;
44

5-
public partial class BrowserStorageService : IStorageService
5+
public partial class WebStorageService : IStorageService
66
{
77
[AutoInject] private SessionStorage sessionStorage;
88
[AutoInject] private LocalStorage localStorage;

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Services.cs

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ public static void AddServerApiProjectServices(this WebApplicationBuilder builde
101101
var builder = policy.AddPolicy<AppResponseCachePolicy>();
102102
}, excludeDefaultPolicy: true);
103103
});
104+
services.AddDistributedMemoryCache();
104105

105106
services.AddHttpContextAccessor();
106107

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/appsettings.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@
158158
"BlazorMode": "BlazorServer",
159159
"BlazorMode_Comment": "BlazorServer, BlazorWebAssembly and BlazorAuto.",
160160
"PrerenderEnabled": false,
161-
"PrerenderEnabled_Comment": "for apps with Prerender enabled, follow the instructions in the service-worker.published.js file"
161+
"PrerenderEnabled_Comment": "for apps with Prerender enabled, follow the instructions in the Client.Web/wwwroot/service-worker.published.js file"
162162
},
163163
"ServerSideHttpClientBaseAddress": null,
164164
"ServerSideHttpClientBaseAddress_Comment": "Read ServerWebSettings.ServerSideHttpClientBaseAddress comments",

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Program.Services.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public static void AddServerWebProjectServices(this WebApplicationBuilder builde
4848
var builder = policy.AddPolicy<AppResponseCachePolicy>();
4949
}, excludeDefaultPolicy: true);
5050
});
51+
services.AddDistributedMemoryCache();
5152

5253
services.AddHttpContextAccessor();
5354

@@ -107,8 +108,9 @@ private static void AddBlazor(WebApplicationBuilder builder)
107108
var configuration = builder.Configuration;
108109

109110
services.AddTransient<IAntiforgery, NoOpAntiforgery>();
110-
services.AddScoped<IAuthTokenProvider, ServerSideAuthTokenProvider>();
111111
services.AddTransient<IPrerenderStateService, WebServerPrerenderStateService>();
112+
services.AddScoped<IExceptionHandler, WebServerExceptionHandler>();
113+
services.AddScoped<IAuthTokenProvider, ServerSideAuthTokenProvider>();
112114
services.AddScoped(sp =>
113115
{
114116
// This HTTP client is utilized during pre-rendering and within Blazor Auto/Server sessions for API calls.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System.Net;
2+
using Boilerplate.Client.Core.Services;
3+
using Boilerplate.Client.Core.Services.Contracts;
4+
5+
namespace Boilerplate.Server.Web.Services;
6+
7+
public partial class WebServerExceptionHandler : ClientExceptionHandlerBase
8+
{
9+
[AutoInject] IHttpContextAccessor httpContextAccessor = default!;
10+
11+
protected override void Handle(Exception exception, ExceptionDisplayKind displayKind, Dictionary<string, object> parameters)
12+
{
13+
if (httpContextAccessor.HttpContext is not null && httpContextAccessor.HttpContext.Response.HasStarted is false)
14+
{
15+
// This method is invoked for exceptions occurring in Blazor Server and during pre-rendering.
16+
// While setting a status code is not meaningful in Blazor Server or streaming pre-rendering
17+
// (since the response has already started), we can still set response codes for non-streaming pre-rendering scenarios.
18+
// A key factor that disables streaming during pre-rendering is response caching (see AppResponseCachePolicy.cs's AppResponseCachePolicy__DisableStreamPrerendering).
19+
// By setting the status code here, we ensure that a faulted response is not cached.
20+
var statusCode = (int)(exception is RestException restExp ? restExp.StatusCode : HttpStatusCode.InternalServerError);
21+
httpContextAccessor.HttpContext.Response.StatusCode = statusCode;
22+
}
23+
24+
base.Handle(exception, displayKind, parameters);
25+
}
26+
}

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/appsettings.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
"BlazorMode": "BlazorServer",
119119
"BlazorMode_Comment": "BlazorServer, BlazorWebAssembly and BlazorAuto.",
120120
"PrerenderEnabled": false,
121-
"PrerenderEnabled_Comment": "for apps with Prerender enabled, follow the instructions in the service-worker.published.js file"
121+
"PrerenderEnabled_Comment": "for apps with Prerender enabled, follow the instructions in the Client.Web/wwwroot/service-worker.published.js file"
122122
},
123123
"ServerSideHttpClientBaseAddress": null,
124124
"ServerSideHttpClientBaseAddress_Comment": "Read ServerWebSettings.ServerSideHttpClientBaseAddress comments",

0 commit comments

Comments
 (0)