發布公告功能需求:執行前/後記錄日誌、異常時導向錯誤頁。直接在 Action 寫導致:
優勢:職責單一、攔截器可復用(多個 Action 共用一組日誌/異常處理邏輯)。
public interface IActionFilter {
void OnActionExecuting(ActionExecutingContext filterContext); // 前置
void OnActionExecuted(ActionExecutedContext filterContext); // 後置
void OnResultExecuting(ResultExecutingContext filterContext); // 結果前
void OnResultExecuted(ResultExecutedContext filterContext); // 結果後
}
兩種實作方式:
ActionFilterAttribute,重寫虛擬方法,標註於 Controller/Action。IActionFilter,重寫虛擬方法,影響該 Controller 所有 Action。public class LogAttribute : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext) {
var action = filterContext.ActionDescriptor.ActionName;
var controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
Log.Info($"[START] {controller}.{action} - Params: {Json.Encode(filterContext.ActionParameters)}");
}
public override void OnActionExecuted(ActionExecutedContext filterContext) {
var action = filterContext.ActionDescriptor.ActionName;
var controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
if (filterContext.Exception != null)
Log.Error($"[ERROR] {controller}.{action}", filterContext.Exception);
else
Log.Info($"[END] {controller}.{action} - Result: {filterContext.Result.GetType().Name}");
}
}
public class HandleErrorAttribute : ActionFilterAttribute {
public override void OnActionExecuted(ActionExecutedContext filterContext) {
if (filterContext.Exception != null && !filterContext.ExceptionHandled) {
// 記錄異常
Log.Fatal("Unhandled exception", filterContext.Exception);
// 導向錯誤視圖
filterContext.Result = new ViewResult { ViewName = "Error" };
filterContext.ExceptionHandled = true; // 標記已處理
// 清除回應內容,避免洩露堆疊追蹤
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusCode = 500;
}
}
}
[Log]
[HandleError]
public class AnnounceController : Controller {
public ActionResult DoRelease(...) { ... } // 自動擁有日誌與異常處理
}
或註冊為全域攔截器:GlobalFilters.Filters.Add(new LogAttribute());(MVC 3+)。
攔截器將「日誌、異常處理、效能監控、授權檢查、快取」等橫切關注點從 Action 抽離,實現 AOP,是 MVC 專案架構乾淨、可維護的關鍵基礎設施。