針對 ASP.NET 專案常見的 NullReferenceException,彙整九大類成因、快速定位技巧與實戰案例,幫助開發者快速止血並建立預防機制。
Tables[0]。Read()。string s; s += "a"; (需 string s = ""; 或 string s = null; 後判斷)。MyClass obj; obj.Method();。Session["user"].ToString() 未檢查。lbl.Text = dr["col"].ToString(); 欄位為 DBNull。FindControl 遞迴。System.NullReferenceException "Thrown"。現象:明明已 `new SqlConnection(connStr)`,呼叫 `Open()` 卻拋出 NullReference,重啟 IIS 恢復。
成因:.NET Framework 1.1 未安裝 SP1 修補程式導致內部欄位初始化競態條件。
解決:安裝 .NET Framework 1.1 SP1 或升級至 2.0+。
高併發下 AppDomain 卸載、Session 遺失、靜態快取被清空。
對策:啟用健康監測、外部化 Session (StateServer/SQLServer/Redis)、實作快取失效重載邏輯。
// 錯誤:頁面類別欄位共用同一 DAL 實例
private DAL dal = new DAL();
// 併發請求同時修改 dal 內部狀態 (如 SqlConnection) 導致互相干擾
修正:每個請求/方法內部 `using (var dal = new DAL())` 或使用 DI 容器管理生命週期 (Scoped)。
開發機編譯參考新版介面,伺服器部署舊版 DLL,介面方法簽章不符導致實例化失敗回傳 null。
檢查:`fuslogvw.exe` (組件繫結失敗記錄)、清除 Bin 目錄重新部署。
| 檢查項目 | 驗證方式 |
|---|---|
| 所有外部輸入 | Request.QueryString/Form/Cookies/Headers 全檢查 null |
| Session/Application/Cache 讀取 | 統一用 `Get |
| 資料庫查詢結果 | DataReader 必須 `if (dr.Read())`;DataTable 檢查 `Rows.Count > 0` |
| 使用者控制項/母版頁控制項 | 用 `FindControl` 遞迴搜尋,不可假設直接存取 |
| ViewState/ControlState | 跨頁 PostBack 驗證 `EnableViewStateMac` 金鑰一致 |
| 相依注入/服務定位器 | 確認容器註冊生命週期 (Transient/Scoped/Singleton) 正確 |
| 第三方庫回傳值 | 查閱文件確認是否可能回傳 null,包裝安全存取 |