try/catch/finally 雖熟悉,但何處捕捉、何時記錄、何時封裝、何時替換、何時重拋往往模糊。合理的異常處理應為場景驅動、可配置,EntLib EHAB 正是優秀選擇。
public class LoginInfo
{
[DisplayName("用戶名")]
[Required(ErrorMessage = "請輸入{0}")]
public string UserName { get; set; }
[DisplayName("密碼")]
[Required(ErrorMessage = "請輸入{0}")]
[DataType(DataType.Password)]
public string Password { get; set; }
}
public class InvalidUserNameException : Exception { }
public class InvalidPasswordException : Exception { }
[ExceptionPolicy("defaultPolicy")]
public class HomeController : ExtendedController
{
public ActionResult Index() => View(new LoginInfo());
[HttpPost]
[HandleErrorAction("OnIndexError")]
public ActionResult Index(LoginInfo loginInfo)
{
if (String.Compare(loginInfo.UserName, "foo", true) != 0)
throw new InvalidUserNameException();
if (loginInfo.Password != "password")
throw new InvalidPasswordException();
return View(loginInfo);
}
[HttpPost]
public ActionResult OnIndexError(LoginInfo loginInfo) => View(loginInfo);
}
見實作篇 web.config 範例:包含 Logging Handler (記錄日誌) + Wrap Handler (封裝為 ApplicationException)。
foo → 拋出 InvalidUserNameException。ExtendedController.OnException 攔截:[ExceptionPolicy("defaultPolicy")] → 策略名 defaultPolicy。ExceptionPolicy.HandleException(ex, "defaultPolicy"):ApplicationException("系統錯誤")。[HandleErrorAction("OnIndexError")] → 找到 OnIndexError Action。HandleErrorActionInvoker 執行 OnIndexError(loginInfo) → 回傳登入 View (保留輸入值)。filterContext.ExceptionHandled = true,流程結束。若為 AJAX 提交 (Request.IsAjaxRequest()),略過 HandleErrorAction,直接回傳 JsonResult 包含異常訊息與堆疊,前端自行處理顯示。
實例展示登入場景下,透過 ExtendedController + EntLib EHAB 實現「拋出業務異常 → 自動套用策略 (記錄+封裝) → 依請求類型回應 (錯誤 Action/JSON/預設 View)」完整閉環。此模式極大降低異常處理樣板碼,提升系統健壯性與維護性。