首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET 統一錯誤處理封裝:ErrorManager 元件設計與應用

     編輯:關於ASP.NET

設計目標

  • 集中管理未處理例外:記錄、通知、友善顯示。
  • 支援定時清理錯誤快取,避免記憶體洩漏。
  • 提供 Session 安全存取包裝,解決 Session 逾時導致的 NullReference。
  • 單一實例模式,全域唯一存取點。

核心類別:ErrorManager

public sealed class ErrorManager
{
 // 單例
 private static readonly Lazy _instance = new Lazy(() => new ErrorManager());
 public static ErrorManager Instance => _instance.Value;

 // 計時器:定期清理過期錯誤
 private Timer _cleanupTimer;
 private readonly TimeSpan _defaultInterval = TimeSpan.FromHours(12);
 private readonly Dictionary _errors = new Dictionary();
 private readonly object _lock = new object();

 private ErrorManager() { }

 // 啟動清理計時器
 public void Start(TimeSpan? interval = null)
 {
 TimeSpan i = interval ?? _defaultInterval;
 _cleanupTimer = new Timer(_ => CleanupExpired(), null, i, i);
 }

 public void SetTimerInterval(TimeSpan interval)
 {
 _cleanupTimer?.Change(interval, interval);
 }

 // 記錄錯誤並回傳唯一 Key
 public string AddError(Exception ex = null)
 {
 ex = ex ?? HttpContext.Current?.Server?.GetLastError();
 if (ex == null) return null;

 string key = Guid.NewGuid().ToString("N");
 var info = new ErrorInfo
 {
 Key = key,
 Time = DateTime.Now,
 Exception = ex,
 Message = ex.Message,
 StackTrace = ex.StackTrace,
 RequestUrl = HttpContext.Current?.Request?.RawUrl,
 User = HttpContext.Current?.User?.Identity?.Name
 };

 lock (_lock) _errors[key] = info;

 // 記錄至日誌框架
 LogError(info);

 return key;
 }

 // 取得錯誤資訊
 public ErrorInfo GetError(string key)
 {
 lock (_lock)
 {
 if (_errors.TryGetValue(key, out var info)) return info;
 return null;
 }
 }

 // 移除錯誤
 public void RemoveError(string key)
 {
 lock (_lock) _errors.Remove(key);
 }

 // 清理過期項目 (預設保留 24 小時)
 private void CleanupExpired(TimeSpan? maxAge = null)
 {
 TimeSpan age = maxAge ?? TimeSpan.FromHours(24);
 var cutoff = DateTime.Now - age;
 List toRemove;
 lock (_lock)
 {
 toRemove = _errors.Where(kvp => kvp.Value.Time < cutoff).Select(kvp => kvp.Key).ToList();
 foreach (var k in toRemove) _errors.Remove(k);
 }
 }

 // Session 安全存取
 public object GetSession(string key)
 {
 var session = HttpContext.Current?.Session;
 return session?[key];
 }

 public void SetSession(string key, object value)
 {
 HttpContext.Current?.Session?.Add(key, value);
 // 或 session[key] = value;
 }

 private void LogError(ErrorInfo info)
 {
 // 整合 log4net/NLog/Serilog
 // log.Error($"[{info.Key}] {info.Message}", info.Exception);
 }
}

public class ErrorInfo
{
 public string Key { get; set; }
 public DateTime Time { get; set; }
 public Exception Exception { get; set; }
 public string Message { get; set; }
 public string StackTrace { get; set; }
 public string RequestUrl { get; set; }
 public string User { get; set; }
}

整合至 Global.asax

public class Global : HttpApplication
{
 protected void Application_Start(object sender, EventArgs e)
 {
 ErrorManager.Instance.Start(); // 啟動定時清理
 // 或 ErrorManager.Instance.SetTimerInterval(TimeSpan.FromHours(6));
 }

 protected void Application_Error(object sender, EventArgs e)
 {
 string key = ErrorManager.Instance.AddError();
 if (!string.IsNullOrEmpty(key))
 {
 // 導向錯誤頁面,攜帶 Key
 Response.Redirect($"~/Error.aspx?key={key}");
 }
 }

 protected void Application_End(object sender, EventArgs e)
 {
 ErrorManager.Instance._cleanupTimer?.Dispose();
 }
}

錯誤顯示頁面 (Error.aspx)

protected void Page_Load(object sender, EventArgs e)
{
 string key = Request.QueryString["key"];
 var error = ErrorManager.Instance.GetError(key);

 if (error != null)
 {
 lblTime.Text = error.Time.ToString("yyyy-MM-dd HH:mm:ss");
 lblMessage.Text = error.Message;
 #if DEBUG
 lblStackTrace.Text = error.StackTrace;
 pnlDebug.Visible = true;
 #endif
 }
 else
 {
 lblMessage.Text = "錯誤資訊已過期或不存在。";
 }
}

進階擴充

  • 分散式快取:將 `_errors` 改用 `IDistributedCache` (Redis),支援 Web Farm。
  • 錯誤分級與通知:依例外類型 (Critical/Warning/Info) 發送 Email、Slack、簡訊。
  • 關聯追蹤:記錄 `CorrelationId` 串聯分散式請求鏈路。
  • 自動重試佇列:暫時性錯誤 (DB Deadlock、網路抖動) 放入 Hangfire/Quartz 重試。

總結

ErrorManager 以單例、字典快取、計時器清理、Session 包裝為核心,提供輕量級錯誤管理基礎設施。生產環境建議替換為成熟日誌框架 + APM (Application Insights、Elastic APM、SkyWalking) 實現全鏈路觀測。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved