首页 > 代码库 > ASP.NET MVC 使 Controller 的 Action 只接受 Ajax 请求。

ASP.NET MVC 使 Controller 的 Action 只接受 Ajax 请求。

首先,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 IsAjaxRequest30         {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         [SuppressMessage("Microsoft.Design","CA1062")]42         public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)43         {44             var isAjaxRequest = controllerContext.HttpContext.Request.IsAjaxRequest();45             return IsAjaxRequest == isAjaxRequest;46         }47     }48 }

PS:实际运用不建议命名空间这样做(与系统类库或泛用第三方类库重合),假如某一天 MVC 团队真的加了这么一个 Attribute,那么就会编译错误了。这里仅作演示,因为暂时想不到一个好的命名空间。-_-|||

那么,只要打上该 Attribute 的 Action,如果构造函数参数为 true 或调用无参构造函数的话,则请求必须为 AJAX 请求。如果构造函数参数为 false,则不能是 AJAX 请求。

如果上述条件不成立,则返回 404 Not Found。

ASP.NET MVC 使 Controller 的 Action 只接受 Ajax 请求。