ActionSelectionAttribute是ASP.NET MVC Preview 5 提供的一個抽象基類,通過ActionSelectionAttribute的命名我們就可以猜想到這個Attribute是用來選擇(匹配)Action方法的。該抽象類別只提供了一個抽象的方法 IsValidForRequest,該方法會在Controller的ActionInvoker被調用。如果一個Action加上了該Attribute,那麼只有當IsValidForRequest方法返回true的時候,當前的請求才會匹配該Action。
AcceptVerbsAttribute是ActionSelectionAttribute的一個實現,AcceptVerbsAttribute用於對不同的HttpMethod(例如"GET","POST","DELETE"等等)而選擇同一Action的不同操作。
例如下面是AcceptVerbsAttribute的一個應用:
注意:兩個Edit的方法簽名不能一樣哦。- -
這個的工作原理大概就是,添加了AcceptVerbsAttribute特性的Action都會調用IsValidForRequest()來檢查當前的HTTP請求中的HTTPMethod中是否為GET或POST,如果和配置的相符,則該Action就會匹配。如果匹配的Action超過一個(例如你上面兩個都設為"GET"),則會拋出異常,如果一個都沒有匹配到,則會調用Controller中的HandleUnknownAction
()方法來處理。
好,下面開始實現我們標題提到的問題。很簡單,就是繼承ActionSelectionAttribute類,並實現它的IsValidForRequest()方法,我麼要暴露一個IsAjax屬性來用於設定該Action是用於Ajax請求還是一般的請求:
GetByAjaxAttribute
public class GetByAjaxAttribute : ActionSelectionAttribute
{
public GetByAjaxAttribute(bool isAjax)
{
this.IsAjax = isAjax;
}
/**//// <summary>
/// 首先我們需要一個屬性來設定該Action是用於Ajax請求還是一般的請求
/// </summary>
public bool IsAjax
{
get;
set;
}
public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
{
//如果為Ajax請求並且設定的IsAjax為true時則返回true
//如果不是Ajax請求並且設定的IsAjax為false時則返回true
//其他返回false
}
}
嘿嘿,是不是覺得很簡單呢,然後我們再具體實現IsValidForRequest()方法就完事了,完整代碼如下,都有注釋了:
GetByAjaxAttribute
public class GetByAjaxAttribute : ActionSelectionAttribute
{
public GetByAjaxAttribute(bool isAjax)
{
this.IsAjax = isAjax;
}
/**//// <summary>
/// 首先我們需要一個屬性來設定該Action是用於Ajax請求還是一般的請求
/// </summary>
public bool IsAjax
{
get;
set;
}
public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
{
/**/////如果是使用jQuery之類的JS架構來進行Ajax請求操作的話,可以使用下面的語句判斷
//string xhr = controllerContext.Controller.ControllerContext.HttpContext.Request.Headers["X-Requested-With"] ?? "";
//這裡使用的是MicrosoftAjax來進行非同步請求,它會在form中添加一個"__MVCASYNCPOST"的標識,我麼可以使用該標識來進行判斷
string xhr = controllerContext.Controller.ControllerContext.HttpContext.Request.Form["__MVCASYNCPOST"] ?? "";
return !(IsAjax ^ (xhr.ToLower() == "true"));
}
}
(對於如何標識是否為Ajax請求,你可以看我的另外一篇文章:一種標記是否為AJAX非同步請求的思路)
該Attribute的使用樣本如下:
Code
[ActionName("Add"), AcceptVerbs("GET")]
public ActionResult AddByGet()
{
ViewData["Message"] = "通過GET方式訪問";
return View();
}
[ActionName("Add"), AcceptVerbs("POST"), GetByAjax(true)]
public ActionResult AddByAjax()
{
//Do Your Thing Here
return Content("通過AJAX的POST方式訪問");
}
//這裡要加上GetByAjax(false)哦,
//否則當POST過來的時候,這個也是合格,
//則會匹配兩個Action(這個和上面一個),就拋出異常了
[ActionName("Add"), AcceptVerbs("POST"), GetByAjax(false)]
public ActionResult AddByPost()
{
//Do Your Thing here
ViewData["Message"] = "通過POST方式訪問";
return View();
}
最後是該文章的的範例程式碼: ActionSelectionAttributeDemo.rar
Enjoy!
參考文章:How a Method Becomes An Action