2012-03-02 45 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一個人嘗試任何無效的網址。