将AjaxOnlyAttribute和ChildActionOnlyAttribute组合为一个操作筛选器
本文关键字:一个 操作 筛选 AjaxOnlyAttribute ChildActionOnlyAttribute 组合 | 更新日期: 2023-09-27 18:26:31
我希望能够标记控制器上的操作,以便通过ajax调用和RenderAction调用。问题是这两个属性都派生或实现了不同的抽象。一条出路是下一条:
[AjaxOnly]
PartialViewResult GetViewAjax(int foo) { return GetView(foo); }
[ChildActionOnly]
PartialViewResult GetView(int foo) { ... }
但这一点都不整洁。
我所说的AjaxOnly属性是:
public sealed class AjaxOnlyAttribute : ActionFilterAttribute
{
#region Public members
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext == null)
throw new ArgumentNullException("filterContext");
if (filterContext.HttpContext.Request.Headers["X-Requested-With"] != "XMLHttpRequest")
filterContext.Result = new HttpNotFoundResult();
}
#endregion
}
此方法取自MVC3期货。为什么条件不是filterContext.HttpContext.Request.IsAjaxRequest()
的一个重要评论是由开发团队提出的,并说:
// Dev10 #939671 - If this attribute is going to say AJAX *only*, then we need to check the header
// specifically, as otherwise clients can modify the form or query string to contain the name/value
// pair we're looking for.
这没有任何意义。这两个属性是互斥的。如果一个操作标记为[ChildActionOnly]
,则客户端永远无法使用HTTP请求(无论是同步还是异步)直接访问该操作。因此,如果您希望使用AJAX访问某个操作,就不应该用[ChildActionOnly]
属性来修饰它。
我不知道这个[AjaxOnly]
属性是什么,它来自哪里,但根据它的实现方式,如果它只依赖于Request.IsAjaxRequest()
方法,您可能需要对它进行调整,以便允许子操作请求。例如,如果它是这样的东西:
public class AjaxOnlyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = new HttpNotFoundResult();
}
}
}
你可能想这样调整:
public class AjaxOrChildActionOnlyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAjaxRequest() &&
!filterContext.IsChildAction
)
{
filterContext.Result = new HttpNotFoundResult();
}
}
}
受Darin的答案和ChildActionOnlyAttribute
的源代码的启发,这是我提出的解决方案,我认为它稍微好一点:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class AjaxOrChildAttribute : ActionMethodSelectorAttribute
{
public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
{
return controllerContext.IsChildAction || controllerContext.RequestContext.HttpContext.Request.IsAjaxRequest();
}
}
这样,验证甚至在尝试执行之前就完成了,如果您键入url,则会出现与尝试任何无效url完全相同的错误。