首先,ajax 請求跟一般的 web 請求本質是相同的,都是 http 請求。理論上服務器端是無法區分該次請求是不是 ajax 請求的,但是,既然標題都已經說了,那么肯定是有辦法做的。
在 ajax 請求的請求報文里,往往會包含這么一條:X-Requested-With = XMLHttpRequest
這在各大的 javascript 框架上也是這么做的。
而服務器端就可以根據這一點來判別,該次的請求是否是 ajax 請求。
而在 ASP.NET MVC 里,也有一個擴展方法:
1 namespace System.Web.Mvc 2 { 3 // 摘要: 4 // 表示一個類,該類對 System.Web.HttpRequestBase 類進行了擴展,在其中添加了確定 HTTP 請求是否為 AJAX 請求的功能。 5 public static class AjaxRequestExtensions 6 { 7 // 摘要: 8 // 確定指定的 HTTP 請求是否為 AJAX 請求。 9 // 10 // 參數: 11 // request: 12 // HTTP 請求。 13 // 14 // 返回結果: 15 // 如果指定的 HTTP 請求是 AJAX 請求,則為 true;否則為 false。 16 // 17 // 異常: 18 // System.ArgumentNullException: 19 // request 參數為 null(在 Visual Basic 中為 Nothing)。 20 public static bool IsAjaxRequest(this HttpRequestBase request); 21 } 22 }
但是呢,這只能在 Action 內部調用了,使得 Action 變得臃腫,需要在 Action 內部分別返回是否是 ajax 請求的結果。
如果能像打上 HttpGet、HttpPost 之類標簽的辦法來做就更好了。
查閱資料得出,要這樣做,需要我們自己寫一個 Attribute,並且這個 Attribute 繼承自抽象類 ActionMethodSelectorAttribute。
那么就好辦了。代碼如下:
1 namespace System.Web.Mvc 2 { 3 /// <summary> 4 /// 表示一個特性,該特性用於限制操作方法,以便該方法僅處理 AJAX 請求。 5 /// </summary> 6 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 7 public sealed class AjaxRequestAttribute : ActionMethodSelectorAttribute 8 { 9 /// <summary> 10 /// 初始化 AjaxRequestAttribute 類的新實例。 11 /// </summary> 12 public AjaxRequestAttribute() 13 : this(true) 14 { 15 } 16 17 /// <summary> 18 /// 初始化 AjaxRequestAttribute 類的新實例。 19 /// </summary> 20 /// <param name="isAjaxRequest">限制操作方法是否是 AJAX 請求。</param> 21 public AjaxRequestAttribute(bool isAjaxRequest) 22 { 23 IsAjaxRequest = isAjaxRequest; 24 } 25 26 /// <summary> 27 /// 指示操作方法是否是 AJAX 請求。 28 /// </summary> 29 public bool IsAjaxRequest 30 { 31 get; 32 private set; 33 } 34 35 /// <summary> 36 /// 確定操作方法 AJAX 請求對指定的控制器上下文是否有效。 37 /// </summary> 38 /// <param name="controllerContext">控制器上下文。</param> 39 /// <param name="methodInfo">有關操作方法的信息。</param> 40 /// <returns>如果操作方法請求對指定的控制器上下文有效,則為 true;否則為 false。</returns> 41 public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo) 42 { 43 if (controllerContext == null) 44 { 45 throw new ArgumentNullException("controllerContext"); 46 } 47 48 bool isAjaxRequest = controllerContext.HttpContext.Request.IsAjaxRequest(); 49 return IsAjaxRequest == isAjaxRequest; 50 } 51 } 52 }
PS:實際運用不建議命名空間這樣做(與系統類庫或泛用第三方類庫重合),假如某一天 MVC 團隊真的加了這么一個 Attribute,那么就會編譯錯誤了。這里僅作演示,因為暫時想不到一個好的命名空間。-_-|||
那么,只要打上該 Attribute 的 Action,如果構造函數參數為 true 或調用無參構造函數的話,則請求必須為 AJAX 請求。如果構造函數參數為 false,則不能是 AJAX 請求。
如果上述條件不成立,則返回 404 Not Found。