♻️ New error page

This commit is contained in:
2025-11-21 23:30:43 +08:00
parent 2a35786204
commit 98b8d5f33b
7 changed files with 141 additions and 109 deletions

View File

@@ -1,26 +1,23 @@
@page
@page "/Error/{statusCode?}"
@model ErrorModel
@{
ViewData["Title"] = "Error";
ViewData["SiteName"] = Model.SiteName ?? "main";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
<div class="h-screen flex justify-center items-center">
<div class="text-center max-w-120">
<img src="~/favicon.png" width="80" height="80" alt="Logo" class="mb-1 mx-auto"/>
<h1 class="text-2xl">@(Model.StatusCode?.ToString() ?? "Error")</h1>
<p>Something went wrong...</p>
<p class="text-sm opacity-80 mt-1">Powered by the Solar Network Pages</p>
<div class="text-xs opacity-70 mt-1">
<p>Path: <b>@Model.CurrentPath</b></p>
<p>Site ID: <b>@(Model.Site?.Id.ToString() ?? "none")</b></p>
@if (Model.ShowRequestId)
{
<p>Request ID: <b>@Model.RequestId</b></p>
}
</div>
</div>
</div>

View File

@@ -1,4 +1,6 @@
using System.Diagnostics;
using DysonNetwork.Shared.Models;
using DysonNetwork.Zone.Publication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
@@ -12,8 +14,20 @@ public class ErrorModel : PageModel
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
[FromRoute] public new int? StatusCode { get; set; }
public SnPublicationSite? Site { get; set; }
public string? SiteName { get; set; }
public string? CurrentPath { get; set; }
public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
if (HttpContext.Items.TryGetValue(PublicationSiteMiddleware.SiteContextKey, out var site))
Site = site as SnPublicationSite;
SiteName = Request.Headers["X-SiteName"].ToString();
CurrentPath = Request.Path;
}
}

View File

@@ -2,22 +2,12 @@
@model IndexModel
@{
ViewData["Title"] = "Solar Network Pages";
ViewData["SiteName"] = Model.SiteName ?? "main";
}
<div class="h-screen flex justify-center items-center">
<div class="text-center max-w-96">
<img src="~/favicon.png" width="80" height="80" alt="Logo" class="mb-1 mx-auto"/>
<h1 class="text-2xl">404 Not Found</h1>
<h1 class="text-2xl">Hello World 👋</h1>
<p>Here are the Solar Network Pages</p>
<p>And you're accessing the site <b>@(Model.SiteName ?? "main")</b></p>
<p class="text-sm opacity-80 mt-1">
The reason you're seeing this is the author of the site
haven't configure anything that match this route.
</p>
<div class="text-xs opacity-70 mt-1">
<p>Path: <b>@Model.CurrentPath</b></p>
<p>Site ID: <b>@(Model.Site?.Id.ToString() ?? "none")</b></p>
</div>
</div>
</div>

View File

@@ -1,70 +1,10 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Zone.Publication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.EntityFrameworkCore;
using System.Text.Json;
namespace DysonNetwork.Zone.Pages;
public class IndexModel(AppDatabase db, PublicationSiteManager psm) : PageModel
public class IndexModel : PageModel
{
public SnPublicationSite? Site { get; set; }
public string? SiteName { get; set; }
public string? CurrentPath { get; set; }
public async Task<IActionResult> OnGet(string? path = null)
public void OnGet()
{
var siteNameValue = Request.Headers["X-SiteName"].ToString();
SiteName = siteNameValue;
CurrentPath = Path.Combine("/", path ?? "");
if (string.IsNullOrEmpty(siteNameValue))
{
SiteName = null;
return Page();
}
var capturedName = siteNameValue;
Site = await db.PublicationSites.FirstOrDefaultAsync(s => s.Slug == capturedName);
if (Site == null) return Page();
var pagePath = CurrentPath;
var page = await db.PublicationPages.FirstOrDefaultAsync(p => p.SiteId == Site.Id && p.Path == pagePath);
if (page != null)
{
switch (page.Type)
{
case PublicationPageType.HtmlPage
when page.Config.TryGetValue("html", out var html) && html is JsonElement content:
return Content(content.ToString(), "text/html");
case PublicationPageType.Redirect
when page.Config.TryGetValue("url", out var url) && url is JsonElement redirectUrl:
return Redirect(redirectUrl.ToString());
}
}
// If the site is enabled the self-managed mode, try lookup the files then
if (Site.Mode == PublicationSiteMode.SelfManaged)
{
var provider = new FileExtensionContentTypeProvider();
var hostedFilePath = psm.GetValidatedFullPath(Site.Id, CurrentPath);
if (System.IO.File.Exists(hostedFilePath))
{
if (!provider.TryGetContentType(hostedFilePath, out var mimeType))
mimeType = "text/html";
var fileStream = new FileStream(hostedFilePath, FileMode.Open, FileAccess.Read);
return new FileStreamResult(fileStream, mimeType);
}
var hostedNotFoundPath = psm.GetValidatedFullPath(Site.Id, "404.html");
if (System.IO.File.Exists(hostedNotFoundPath))
{
var fileStream = new FileStream(hostedNotFoundPath, FileMode.Open, FileAccess.Read);
return new FileStreamResult(fileStream, "text/html");
}
}
return Page();
}
}