2013-11-20 99 views
2

我有一個現有的站點,它的所有控制器都有一個基本控制器類,它覆蓋OnAuthorization的實現。在最簡單的減少形式:Filter.OnAuthorization在Controller.OnAuthorization之前運行

protected override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    base.OnAuthorization(filterContext); 
    //Do Stuff 
} 

這一切工作正常,以及在合適的時間做它想要的。我現在想要添加一個新的全局授權,它將在所有其他授權屬性之前運行。爲了測試這個屬性是這樣的:

public class TestFilterAttribute : FilterAttribute, IAuthorizationFilter 
{ 

    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     var text = "debug point"; 
     return; 
    } 
} 

,並加入到全局過濾器是這樣的:

filters.Add(new TestFilterAttribute()); 

我的問題是控制器的OnAuthorization似乎總是在我的過濾器的一個運行。有什麼方法可以改變這個嗎?我已經嘗試使用可以在將其添加到全局過濾器集合時設置的order屬性來玩,但這似乎沒有幫助。

我可能會將控制器的OnAuthorization的邏輯移動到一個新的過濾器屬性,當訂單可能可用時,但我寧願避免重大代碼重組,如果有更簡單的方法來做到這一點。

我一直在尋找關於Controller.OnAuthorization方法的信息,但我發現的最好的方法是http://msdn.microsoft.com/en-us/library/gg416513(v=vs.98).aspx,它只談論過濾器。我曾假設他們會在控制器上以相同的方式工作,但他們似乎正在得到專門處理,尤其是不考慮訂單(即使int.MinValue不是首先進入,所以它不僅僅是控制器默認情況下的訂單非常低)。

因此,有關如何獲得身份驗證過濾器作爲第一件事情運行的任何建議?

回答

2

最終的解決方案是重構代碼。我採用了所有可以在過濾器屬性上運行的方法(例如OnAuthorization,OnActionExecuting等),並將它們移動到爲它們來自的類命名的屬性上。因此BasicControllerOnAuthorization成爲BasicControllerAttribute上的相同方法。

然後將這些屬性應用於控制器,然後由所有從BasicController繼承的類繼承屬性,從而基本上保持相同的功能。

但是,該屬性可以有其Order設置,允許您隨意運行運行順序。

我從這裏得到的結果是永遠不會覆蓋控制器上的這些方法,並始終使用屬性。 :)

+0

好課。我一直喜歡過濾器屬性。感謝您分享您的解決方案。 – Nico

+0

是的,從這條路上開始,我已經做了大量的過濾器屬性來完成各種各樣的事情(各種安全測試,否則最終會被單獨放在每個相關的動作中)。我正在考慮的下一件事是擴展傳入其完整對象的ID的屬性。 :) – Chris

1

我有一個與Controller.OnAuthorization和AuthorizationFilter.OnAuthorization方法執行順序相關的問題。

  • 簡短的回答是:你不能覆蓋Controller.OnAuthorization之前,其他過濾器 運行。

  • 對「爲什麼這樣?」這個問題的詳細答案。在下面的代碼中,來自 的ASP.NET MVC源代碼。

  • 還有不錯的博文filter ordering

版權所有(c)Microsoft Open Technologies,Inc.保留所有權利。有關許可證信息,請參閱項目根目錄中的License.txt

FilterProviders.cs

namespace System.Web.Mvc 
{ 
    public static class FilterProviders 
    { 
     static FilterProviders() 
     { 
      Providers = new FilterProviderCollection(); 
      Providers.Add(GlobalFilters.Filters); 
      Providers.Add(new FilterAttributeFilterProvider()); 
      Providers.Add(new ControllerInstanceFilterProvider()); 
     } 

     public static FilterProviderCollection Providers { get; private set; } 
    } 
} 

ControllerInstanceFilterProvider.cs

using System.Collections.Generic; 

namespace System.Web.Mvc 
{ 
    public class ControllerInstanceFilterProvider : IFilterProvider 
    { 
     public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) 
     { 
      if (controllerContext.Controller != null) 
      { 
       // Use FilterScope.First and Order of Int32.MinValue to ensure controller instance methods always run first 
       yield return new Filter(controllerContext.Controller, FilterScope.First, Int32.MinValue); 
      } 
     } 
    } 
} 
+0

謝謝。很高興看到一些代碼來支持我的發現。我試圖找到它,但這東西似乎陷入了抽象迷宮。 :) – Chris