From 747e70ca0032d0aad95302dbda47bf778a95333e Mon Sep 17 00:00:00 2001 From: Damian Edwards Date: Tue, 17 Dec 2024 10:39:48 -0800 Subject: [PATCH] Make developer exception page work during dev in the sample --- samples/RazorSlices.Samples.WebApp/Program.cs | 10 ++++ .../Properties/launchSettings.json | 6 ++- .../ResponseBufferingMiddleware.cs | 52 +++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 samples/RazorSlices.Samples.WebApp/ResponseBufferingMiddleware.cs diff --git a/samples/RazorSlices.Samples.WebApp/Program.cs b/samples/RazorSlices.Samples.WebApp/Program.cs index ad1c9bd..5ab302c 100644 --- a/samples/RazorSlices.Samples.WebApp/Program.cs +++ b/samples/RazorSlices.Samples.WebApp/Program.cs @@ -22,6 +22,16 @@ app.UseStatusCodePages(); app.UseStaticFiles(); +if (app.Environment.IsDevelopment()) +{ + app.UseDeveloperExceptionPage(); + if (Environment.GetEnvironmentVariable("ENABLE_RESPONSE_BUFFERING") == "true") + { + // Enable response buffering middleware to allow for response interception during local development + app.UseResponseBuffering(); + } +} + app.MapGet("/lorem", () => Results.Redirect("/lorem-static")); app.MapGet("/lorem-static", () => Results.Extensions.RazorSlice()); app.MapGet("/lorem-dynamic", (int? paraCount, int? paraLength) => diff --git a/samples/RazorSlices.Samples.WebApp/Properties/launchSettings.json b/samples/RazorSlices.Samples.WebApp/Properties/launchSettings.json index a436f57..4d606c3 100644 --- a/samples/RazorSlices.Samples.WebApp/Properties/launchSettings.json +++ b/samples/RazorSlices.Samples.WebApp/Properties/launchSettings.json @@ -6,7 +6,8 @@ "launchBrowser": true, "applicationUrl": "http://localhost:5270", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "ENABLE_RESPONSE_BUFFERING": "true" } }, "https": { @@ -15,7 +16,8 @@ "launchBrowser": true, "applicationUrl": "https://localhost:7194;http://localhost:5270", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "ENABLE_RESPONSE_BUFFERING": "true" } } } diff --git a/samples/RazorSlices.Samples.WebApp/ResponseBufferingMiddleware.cs b/samples/RazorSlices.Samples.WebApp/ResponseBufferingMiddleware.cs new file mode 100644 index 0000000..322a447 --- /dev/null +++ b/samples/RazorSlices.Samples.WebApp/ResponseBufferingMiddleware.cs @@ -0,0 +1,52 @@ +namespace RazorSlices.Samples.WebApp; + +using System.IO; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; + +internal sealed class ResponseBufferingMiddleware(RequestDelegate next) +{ + public async Task InvokeAsync(HttpContext context) + { + // Save the original response body stream + var originalBodyStream = context.Response.Body; + + try + { + // Create a memory stream to buffer the response + using var memoryStream = new MemoryStream(); + context.Response.Body = memoryStream; + + // Call the next middleware + await next(context); + + // If no exception occurs, write the buffered response to the original body + memoryStream.Seek(0, SeekOrigin.Begin); + await memoryStream.CopyToAsync(originalBodyStream); + } + catch + { + // Clear the existing response + context.Response.Clear(); + context.Response.StatusCode = StatusCodes.Status500InternalServerError; + + // Rethrow to let the Developer Exception Page middleware handle it + throw; + } + finally + { + // Restore the original body stream + context.Response.Body = originalBodyStream; + } + } +} + +internal static class ResponseBufferingMiddlewareExtensions +{ + public static IApplicationBuilder UseResponseBuffering(this IApplicationBuilder app) + { + return app.UseMiddleware(); + } +} +