2012-03-02 47 views
7

我希望能够在控制器上标记一个动作,以便通过ajax调用和通过RenderAction调用。问题是这两个属性都派生或实现了不同的抽象。下一步是出路:将AjaxOnlyAttribute和ChildActionOnlyAttribute合并为一个动作过滤器

[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. 

回答

16

这没有任何意义。这两个属性是相互排斥的。如果一个动作被标记为[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(); 
     } 
    } 
} 
+0

为什么?假设您的动作通过RenderAction()和ajax请求从不同的地方重新使用。假设它们在不同的页面上被重复使用,就像在许多地方绘制一些标准的工具面板一样,并且在不同的环境下使用略有不同 – 2012-03-02 13:50:43

+0

@Hohhi,所以你希望你的行为只能通过AJAX调用或者作为Child action ? – 2012-03-02 14:00:04

+0

的确如此,感谢您的建议,我会更新问题并告诉我在一段时间内有多远 – 2012-03-02 14:06:49

1

启发对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(); 
    } 
} 

这种方式,验证甚至试图执行之前完成,如果你在网址栏中输入你的错误是确切的SAM一个人尝试任何无效的网址。