Show real exception details to admins on the error page (diagnostics)
CI/CD / CI · dotnet build (push) Successful in 42s
CI/CD / Deploy · hamkadr (push) Successful in 1m4s

Production hides the exception behind a generic 500, so a logged-in Admin couldn''t see why a page
(e.g. /Admin/Settings) failed. Surface the exception type/message/inner/stack on the /Error page ONLY
when the current user is in the Admin role; everyone else still sees the generic message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-23 15:14:20 +03:30
parent 2d4ea3a762
commit 9fc83b231b
2 changed files with 25 additions and 0 deletions
+9
View File
@@ -14,6 +14,15 @@
</p>
}
@if (Model.AdminDetail is not null)
{
<div style="margin:16px 0; padding:14px; border:1px solid var(--danger); border-radius:10px; background:#fff5f5; direction:ltr; text-align:left;">
<strong>🔧 جزئیات خطا (فقط برای ادمین)</strong>
@if (Model.AdminPath is not null) { <div style="margin:6px 0;"><code>@Model.AdminPath</code></div> }
<pre style="white-space:pre-wrap; word-break:break-word; font-size:12px; margin:8px 0 0; max-height:50vh; overflow:auto;">@Model.AdminDetail</pre>
</div>
}
<h3>Development Mode</h3>
<p>
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
+16
View File
@@ -1,4 +1,5 @@
using System.Diagnostics;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
@@ -12,9 +13,24 @@ public class ErrorModel : PageModel
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
/// <summary>The real exception — shown ONLY to a logged-in Admin, so production 500s can be
/// diagnosed without server-log access. Hidden from everyone else.</summary>
public string? AdminDetail { get; private set; }
public string? AdminPath { get; private set; }
public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
if (User.IsInRole("Admin"))
{
var feat = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
AdminPath = feat?.Path;
if (feat?.Error is { } ex)
AdminDetail = ex.GetType().FullName + ": " + ex.Message
+ (ex.InnerException is { } ie ? $"\n ↳ {ie.GetType().Name}: {ie.Message}" : "")
+ "\n\n" + ex.StackTrace;
}
}
}