Runtime Error
Description: An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine.
**核心含義**:應用程式發生未處理例外,但 `web.config` 設定 `
<!-- web.config -->
<configuration>
<system.web>
<!-- mode="Off":所有環境顯示詳細錯誤 (含堆疊) -->
<customErrors mode="Off" />
</system.web>
</configuration>
重新整理頁面,即可看到完整 **黃色死機畫面 (YSOD)**,包含例外類型、訊息、堆疊追蹤、原始碼行號。
<configuration>
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="~/Error/General.aspx">
<error statusCode="404" redirect="~/Error/404.aspx" />
<error statusCode="500" redirect="~/Error/500.aspx" />
</customErrors>
</system.web>
</configuration>
<!-- Error/500.aspx -->
<%@ Page Language="C#" %>
<!DOCTYPE html>
<html>
<head><title>系統錯誤</title></head>
<body>
<h1>抱歉,系統發生錯誤 (500)</h1>
<p>我們已記錄此錯誤,技術人員會盡快處理。</p>
<p><a href="/">返回首頁</a></p>
<!-- 可選:顯示錯誤參考代碼 (從 Session/QueryString 取得) -->
<% if (Request.QueryString["errId"] != null) { %>
<p>錯誤參考代碼:<%= Request.QueryString["errId"] %></p>
<% } %>
</body>
</html>
// Global.asax.cs
protected void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
// 1. 記錄完整堆疊至 Log (log4net / NLog / Serilog / Enterprise Library)
Logger.Error(ex, "Unhandled exception");
// 2. 取得 HttpException 狀態碼
var httpEx = ex as HttpException;
int statusCode = httpEx?.GetHttpCode() ?? 500;
// 3. 清除錯誤,避免預設處理
Server.ClearError();
// 4. 導向對應錯誤頁 (帶上錯誤 ID 供查詢)
string errorId = Guid.NewGuid().ToString("N").Substring(0, 8);
Response.Redirect($"~/Error/{statusCode}.aspx?errId={errorId}");
}
| 類別 | 典型原因 | 排查方向 |
|---|---|---|
| 設定錯誤 | web.config 格式錯誤、區段重複、權限不足讀取設定 | 檢查 Event Viewer → Application → ASP.NET 事件;啟用 ` |
| 編譯錯誤 | .aspx/.cshtml 語法錯誤、缺少命名空間、型別不符 | YSOD 會直接顯示編譯錯誤行號 |
| 資料庫連線 | 連線字串錯誤、SQL Server 未啟動、防火牆、權限不足、連線池耗盡 | 檢查連線字串、SQL Log、連線池大小設定 |
| Null 參考 | Session/ViewState 為 null、資料庫查無資料直接 .ToString()、物件未初始化 | 堆疊追蹤定位行號,加入防禦性檢查 `?.` / `??` |
| 權限/信任 | 檔案寫入無權限、登錄存取拒絕、Medium Trust 限制、CAS 政策 | 檢查應用程式池身分 (ApplicationPoolIdentity) 資料夾權限 |
| 第三方元件 | DLL 版本衝突 (DLL Hell)、缺少相依組件、授權過期、非托管記憶體洩漏 | Fusion Log (fuslogvw) 追蹤組件載入失敗 |
| ASP.NET 未正確註冊至 IIS | 安裝 .NET 後未執行 `aspnet_regiis -i`、IIS 版本不匹配、應用程式池 .NET 版本錯誤 | 見下方修復步驟 |
**適用情境**:安裝 .NET Framework 後、安裝/升級 IIS 後、手動刪除 IIS 註冊腳本後、應用程式池顯示「未識別的 Managed 版本」。
REM .NET Framework 2.0 / 3.5 (經典模式)
C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -i
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_regiis.exe -i
REM .NET Framework 4.x (整合模式)
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -i
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -i
REM .NET Framework 4.6.2+ / Windows 10 / Server 2016+ (建議用 DISM)
dism /online /enable-feature /featurename:IIS-ASPNET45 /all
dism /online /enable-feature /featurename:IIS-ASPNET /all
REM 驗證註冊結果
aspnet_regiis.exe -lv
-- 輸出應包含版本號與 "Installed" 狀態
核心心法:**Runtime Error 只是遮罩,YSOD 才是真相;環境問題靠註冊修復,代碼問題靠堆疊定位;生產環境永遠不顯示堆疊給使用者。**