From 833a98278a7fb498e61735475fbfc8ad7b7b4ea9 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Thu, 26 Oct 2023 13:09:16 -0700 Subject: [PATCH] Use shape when rendering Http errors to allow cusomization from the UI (#14545) --- .../Controllers/DiagnosticsController.cs | 29 +++++---------- .../ViewModels/HttpErrorShapeViewModel.cs | 35 +++++++++++++++++++ .../Views/Diagnostics/Error.cshtml | 2 +- ...est.cshtml => HttpError-BadRequest.cshtml} | 2 +- ...dden.cshtml => HttpError-Forbidden.cshtml} | 0 ...Found.cshtml => HttpError-NotFound.cshtml} | 0 ...d.cshtml => HttpError-Unauthorized.cshtml} | 0 .../Views/HttpError.cshtml | 3 ++ ...Found.liquid => HttpError-NotFound.liquid} | 0 ...Found.liquid => HttpError-NotFound.liquid} | 0 src/docs/reference/README.md | 1 + .../reference/modules/Diagnostics/README.md | 34 ++++++++++++++++++ src/docs/releases/1.8.0.md | 10 ++++-- 13 files changed, 92 insertions(+), 24 deletions(-) create mode 100644 src/OrchardCore.Modules/OrchardCore.Diagnostics/ViewModels/HttpErrorShapeViewModel.cs rename src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/{Diagnostics/BadRequest.cshtml => HttpError-BadRequest.cshtml} (78%) rename src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/{Diagnostics/Forbidden.cshtml => HttpError-Forbidden.cshtml} (100%) rename src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/{Diagnostics/NotFound.cshtml => HttpError-NotFound.cshtml} (100%) rename src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/{Diagnostics/Unauthorized.cshtml => HttpError-Unauthorized.cshtml} (100%) create mode 100644 src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError.cshtml rename src/OrchardCore.Themes/TheAgencyTheme/Views/{Shared/NotFound.liquid => HttpError-NotFound.liquid} (100%) rename src/OrchardCore.Themes/TheBlogTheme/Views/{Shared/NotFound.liquid => HttpError-NotFound.liquid} (100%) create mode 100644 src/docs/reference/modules/Diagnostics/README.md diff --git a/src/OrchardCore.Modules/OrchardCore.Diagnostics/Controllers/DiagnosticsController.cs b/src/OrchardCore.Modules/OrchardCore.Diagnostics/Controllers/DiagnosticsController.cs index dedea5b64b9..980903f1b17 100644 --- a/src/OrchardCore.Modules/OrchardCore.Diagnostics/Controllers/DiagnosticsController.cs +++ b/src/OrchardCore.Modules/OrchardCore.Diagnostics/Controllers/DiagnosticsController.cs @@ -1,27 +1,16 @@ -using System; -using System.Net; using Microsoft.AspNetCore.Mvc; +using OrchardCore.Diagnostics.ViewModels; -namespace OrchardCore.Diagnostics.Controllers +namespace OrchardCore.Diagnostics.Controllers; + +public class DiagnosticsController : Controller { - public class DiagnosticsController : Controller + [IgnoreAntiforgeryToken] + public IActionResult Error(int? status) { - [IgnoreAntiforgeryToken] - public IActionResult Error(int? status) - { - // Most commonly used error messages. - ViewData["StatusCode"] = status; - Enum.TryParse((status ?? 500).ToString(), true, out HttpStatusCode httpStatusCode); - + // Most commonly used error messages. + ViewData["StatusCode"] = status; - return httpStatusCode switch - { - HttpStatusCode.Forbidden => View("Forbidden"), - HttpStatusCode.NotFound => View("NotFound"), - HttpStatusCode.BadRequest => View("BadRequest"), - HttpStatusCode.Unauthorized => View("Unauthorized"), - _ => View("Error"), - }; - } + return View(new HttpErrorShapeViewModel(status)); } } diff --git a/src/OrchardCore.Modules/OrchardCore.Diagnostics/ViewModels/HttpErrorShapeViewModel.cs b/src/OrchardCore.Modules/OrchardCore.Diagnostics/ViewModels/HttpErrorShapeViewModel.cs new file mode 100644 index 00000000000..be7d55a1f86 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Diagnostics/ViewModels/HttpErrorShapeViewModel.cs @@ -0,0 +1,35 @@ +using System; +using System.Net; +using OrchardCore.DisplayManagement.Views; + +namespace OrchardCore.Diagnostics.ViewModels; + +public class HttpErrorShapeViewModel : ShapeViewModel +{ + private const string ShapeType = "HttpError"; + + public int? Code { get; set; } + + public HttpStatusCode? HttpStatusCode { get; } + + public HttpErrorShapeViewModel(int? code) + { + Code = code; + + // The type name is 'HttpError', which means any Http status code will be handled by the 'HttpError.cshtml' or 'HttpError.liquid'. + Metadata.Type = ShapeType; + + if (code.HasValue && Enum.TryParse(Code.ToString(), out var httpStatusCode)) + { + HttpStatusCode = httpStatusCode; + + // Assign an alternative for every status-code to enable the customization for each status. + + // (ex. 'HttpError-404.cshtml' or 'HttpError-404.liquid') + Metadata.Alternates.Add($"{ShapeType}__{Code}"); + + // (ex. 'HttpError-NotFound.cshtml' or 'HttpError-NotFound.liquid') + Metadata.Alternates.Add($"{ShapeType}__{httpStatusCode}"); + } + } +} diff --git a/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/Error.cshtml b/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/Error.cshtml index 709e3c06fe4..32eceece3e6 100644 --- a/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/Error.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/Error.cshtml @@ -1 +1 @@ -

@T["An error occurred while executing this request."]

+@await DisplayAsync(Model) diff --git a/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/BadRequest.cshtml b/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError-BadRequest.cshtml similarity index 78% rename from src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/BadRequest.cshtml rename to src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError-BadRequest.cshtml index 99fd9d9efd2..3b4f2a752d8 100644 --- a/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/BadRequest.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError-BadRequest.cshtml @@ -1 +1 @@ -

@T["Your browser sent a request that this server could not understand."]

\ No newline at end of file +

@T["Your browser sent a request that this server could not understand."]

diff --git a/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/Forbidden.cshtml b/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError-Forbidden.cshtml similarity index 100% rename from src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/Forbidden.cshtml rename to src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError-Forbidden.cshtml diff --git a/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/NotFound.cshtml b/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError-NotFound.cshtml similarity index 100% rename from src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/NotFound.cshtml rename to src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError-NotFound.cshtml diff --git a/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/Unauthorized.cshtml b/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError-Unauthorized.cshtml similarity index 100% rename from src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/Diagnostics/Unauthorized.cshtml rename to src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError-Unauthorized.cshtml diff --git a/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError.cshtml b/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError.cshtml new file mode 100644 index 00000000000..2e1d7b0f435 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Diagnostics/Views/HttpError.cshtml @@ -0,0 +1,3 @@ +@model OrchardCore.Diagnostics.ViewModels.HttpErrorShapeViewModel + +

@T["An error occurred while executing this request."]

diff --git a/src/OrchardCore.Themes/TheAgencyTheme/Views/Shared/NotFound.liquid b/src/OrchardCore.Themes/TheAgencyTheme/Views/HttpError-NotFound.liquid similarity index 100% rename from src/OrchardCore.Themes/TheAgencyTheme/Views/Shared/NotFound.liquid rename to src/OrchardCore.Themes/TheAgencyTheme/Views/HttpError-NotFound.liquid diff --git a/src/OrchardCore.Themes/TheBlogTheme/Views/Shared/NotFound.liquid b/src/OrchardCore.Themes/TheBlogTheme/Views/HttpError-NotFound.liquid similarity index 100% rename from src/OrchardCore.Themes/TheBlogTheme/Views/Shared/NotFound.liquid rename to src/OrchardCore.Themes/TheBlogTheme/Views/HttpError-NotFound.liquid diff --git a/src/docs/reference/README.md b/src/docs/reference/README.md index 4f200db6509..62bc65c72cd 100644 --- a/src/docs/reference/README.md +++ b/src/docs/reference/README.md @@ -117,6 +117,7 @@ Here's a categorized overview of all built-in Orchard Core features at a glance. - [Email](modules/Email/README.md) - [Redis](modules/Redis/README.md) - [Deployment](modules/Deployment/README.md) +- [Diagnostics](modules/Diagnostics/README.md) - [Remote Deployment](modules/Deployment.Remote/README.md) - [Sms](modules/Sms/README.md) diff --git a/src/docs/reference/modules/Diagnostics/README.md b/src/docs/reference/modules/Diagnostics/README.md new file mode 100644 index 00000000000..6caabf8cc29 --- /dev/null +++ b/src/docs/reference/modules/Diagnostics/README.md @@ -0,0 +1,34 @@ +# Diagnostics (`OrchardCore.Diagnostics`) + +## Purpose + +Enables you to present HTTP errors in a personalized style and offers a means to modify the response of particular HTML errors. By default, we utilizes the following templates. + +| Template | Description | +| --------- | ----------- | +| `HttpError__BadRequest` | Generates the `400` HTTP error page. You can adjust its appearance by modifying the `HttpError-BadRequest.cshtml` or `HttpError-BadRequest.liquid` views. | +| `HttpError__Forbidden` | Generates the `403` HTTP error page. You can adjust its appearance by modifying the `HttpError-Forbidden.cshtml` or `HttpError-Forbidden.liquid` views. | +| `HttpError__NotFound` | Generates the `404` HTTP error page. You can adjust its appearance by modifying the `HttpError-NotFound.cshtml` or `HttpError-NotFound.liquid` views. | +| `HttpError__Unauthorized` | Generates the `401` HTTP error page. You can adjust its appearance by modifying the `HttpError-Unauthorized.cshtml` or `HttpError-Unauthorized.liquid` views. | +| `HttpError__HttpStatusCode` | Fallback template which generates the HTTP error page when no explicit template defined (ex, `HttpError-MethodNotAllowed.cshtml`). You can adjust its appearance by modifying the `HttpError.cshtml` or `HttpError.liquid` views. | + + +### Example + +To alter the presentation of a particular HTTP status code, you can easily create a template within your theme that corresponds to the HTTP status code. For instance, if you wish to customize the 404 error page, you can achieve this by creating a template in your theme named `HttpError-NotFound.cshtml` or `HttpError-NotFound.liquid` as outlined below. + +``` +

@T["The page could not be found."]

+``` + +We utilize a template named `HttpError` to structure the default output of the undefined error. + +## Utilizing the Templates Feature for Customizing Error Pages + +You can utilize the [Templates](../Templates/README.md) feature to modify the appearance of your error pages. + +To illustrate, if you want to alter the view of the `403 (Forbidden)` page using the Template feature, create a new Template named `HttpError__Forbidden` and insert your customized HTML as follows: + +``` +

{{ "You do not have access permission to this page." | t }}

+``` diff --git a/src/docs/releases/1.8.0.md b/src/docs/releases/1.8.0.md index fea359a8af4..956695bc3b8 100644 --- a/src/docs/releases/1.8.0.md +++ b/src/docs/releases/1.8.0.md @@ -12,9 +12,9 @@ The `TheAdmin` theme was upgraded to Bootstrap 5.3.2. Here is a list of the brea - The `darkmode` theme is now called `dark`. - The `default` theme is now called `light`. - By default, the theme is set to `auto` which allows us to use the default device color preference. - - Metrial-icons are no longer included. + - Material-icons are no longer included. - The `DarkModeService.cs` was replaced with `ThemeTogglerService`. - - The prperty named `DisplayDarkMode` in `AdminSettings` was replaced with `DisplayThemeToggler`. + - The property named `DisplayDarkMode` in `AdminSettings` was replaced with `DisplayThemeToggler`. - Bootstrap is no longer compiled in `TheAdmin.css`. Bootstrap are loaded independently for performance and maintainability reasons. ### Workflow Module @@ -32,6 +32,12 @@ A new option for restarting a specific Workflow instance has been incorporated, The `NavbarTop` zone is no longer used in the `TheAdmin` or `TheTheme` themes. Follow the Navbar details below on how to inject custom menu items in the navbar. +### Diagnostics Module + +The HTTP error views are now in the form of shapes. If you've made customizations to error views within your theme, you should search for `BadRequest`, `Forbidden`, `NotFound`, and `Unauthorized` views in either `YourTheme/Views/OrchardCore.Diagnostics/Diagnostics` or `YourTheme/Views/Shared` and relocate them to `YourTheme/Views`. Afterwards, append `HttpError-` to their names. For instance, `NotFound.cshtml` should be renamed to `HttpError-NotFound.cshtml`. + +Additionally, if you've customized the `Error.cshtml` view, it should be renamed to `HttpError.cshtml` since it acts as the default template for error pages. + ## Change Logs ### TheTheme Theme