初學ASP.NET MVC 學習筆記(八)-Action Filters
Understanding Action Filters
最近在做一個填寫基本資料的View,在寫年齡的DrowDownList的時候,
因為求快,所以就直接在View上寫了一個下面的Code:
<% List<string> ageList = new List<string>();
for (int i = 1; i <= 10;i++ )
{
ageList.Add(i.ToString());
}
%>
<div>
年齡:<%=Html.DropDownList("Age", new SelectList(ageList)) %>
</div>
雖然出來的結果是成功的,但是把程式寫在View中,就違反了MVC的精神,也因此被念了一下。
後來我就把這段Code拿到Controller中去寫:
Controller
public ActionResult Index()
{
List<string> ageList = new List<string>();
for (int i = 1; i <= 10; i++)
{
ageList.Add(i.ToString());
}
ViewData["AgeSelectList"] = new SelectList(ageList);
return View();
}
View
<%var age = ViewData["AgeSelectList"] as SelectList;%>
<div>
年齡:<%=Html.DropDownList("Age", age) %>
</div>
出來的結果跟剛剛的一樣,View上也變得比較乾淨,但是呢,如果當Controller中有其他邏輯
譬如說寫入資料庫失敗的時候返回View,只要沒有run到這段Code,程式就會出錯
例如我隨便拋出一個Exception,然後直接返回View
public ActionResult Index()
{
try
{
throw new Exception();
List<string> ageList = new List<string>();
for (int i = 1; i <= 10; i++)
{
ageList.Add(i.ToString());
}
ViewData["AgeSelectList"] = new SelectList(ageList);
return View();
}
catch
{
return View();
}
}
就會出現上面的錯誤訊息。
所以一種方法就是在每次返回View前,都將SelectList的ViewData準備好,不過這樣實在太累也太笨
或是在剛進到Action時就把ViewData準備好,好像也不是什麼好方法…
所以我試了下面兩種方法:分別是用BaseController跟Action Filter
BaseController的方法就是先建一個中繼的Controller,讓他繼承Controller,
再讓每個自訂Controller繼承他,變成如下
public class BaseController:Controller
{
public BaseController()
{
List<string> ageList = new List<string>();
for (int i = 1; i <= 10; i++)
{
ageList.Add(i.ToString());
}
ViewData["AgeSelectList"] = new SelectList(ageList);
}
}
public class HomeController : BaseController
{
public ActionResult Index()
{
try
{
throw new Exception();
return View();
}
catch
{
return View();
}
}
}
把我要的ViewData放在BaseController的建構子裡,只要Controller有繼承他,就會有ViewData可以用
雖然很方便,但是壞處就是不需要用到的Action也會經過BaseController,如果在BaseController中寫
太多Code對效能不太好,所以接下來改用Action Filter的方式解決‧
自訂一個Class,然後繼承ActionFilterAttribute,再override OnActionExecuted 這個方法:
public class AgeFilter:ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
List<string> ageList = new List<string>();
for (int i = 1; i <= 10; i++)
{
ageList.Add(i.ToString());
}
filterContext.Controller.ViewData["AgeSelectList"] = new SelectList(ageList);
}
}
之後只要在需要調用的Action上加一個Attribute
[AgeFilter] //<===加上自定的Filter Attribute
public ActionResult Index()
{
try
{
throw new Exception();
return View();
}
catch
{
return View();
}
}
就可以用了。
Action Filter好用的地方不只在這,例如在發生例外要把錯誤訊息Mail到信箱
或是在未登入的時候,要做某些事情,都可以用Action Filter來處理。