2011-04-06 133 views
10

我有一個自定義的授權類,從FilterAttribute繼承並實現IAuthorizationFilter。我正在使用最新版本的Ninject w/asp.net MVC 3支持。自定義授權MVC 3和Ninject IoC

我遇到的問題是我使用構造函數注入來注入存儲庫。但在OnAuthorization被調用時,存儲庫爲空。下面是代碼...

public class MyAuthorizeAttribute : FilterAttribute, IAuthorizationFilter 
    { 
     private readonly IMyRepo _MyRepo; 

     public MyAuthorizeAttribute() { } 
     public MyAuthorizeAttribute(IMyRepo myRepo) 
     { 
      _MyRepo= myRepo; //this gets initialized 
     } 


     public void OnAuthorization(AuthorizationContext filterContext) 
     { 
      _MyRepo.DoStuff(); //<< Null, wtf 

     } 
    } 

濾膜結合:

Bind<IMyRepo>().To<MyRepo>().InRequestScope(); 


this.BindFilter<MyAuthorizeAttribute >(System.Web.Mvc.FilterScope.Controller, null).WhenControllerHas<MyAuthorizeAttribute >(); 

更新: 有一件事我注意到的是此過濾器是在控制器級別。我在行動範圍內有其他過濾器,似乎可以正常工作......這可能是原因嗎?

更新2: 我已經證實,如果我改變過濾範圍的行動,那麼庫也OnAuthorization(NOT NULL)。

這工作如下,但我需要在控制器範圍,而不是行動。

this.BindFilter<MyAuthorizeAttribute >(System.Web.Mvc.FilterScope.Action, null).WhenActionMethodHas<MyAuthorizeAttribute >(); 
+0

它看起來像你的MyAuthorizeAttribute被默認構造函數調用。 – dexter 2011-04-06 20:01:36

+0

@dexter,不'認爲是這樣。我把斷點和ctor與repo叫做 – 2011-04-06 20:04:52

+0

你在Ninject模塊中設置了過濾器綁定嗎?請參閱http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/#more-2004中的「過濾器的依賴注入」一節下的示例代碼 – WorldIsRound 2011-04-06 20:08:03

回答

9

屬性不支持構造函數注入,因爲它們是由.NET Framework創建的,並且不受Ninject控制。如果你真的想使用FilterAttribute(我不建議),你必須使用屬性注入。

而是繼續你剛剛開始的。您需要一個實現IAuthorizationFilter的過濾器(不是派生自FilterAttribute,只是將其從您的代碼中移除),另外還需要一個標記控制器/操作的普通屬性。

然後更改綁定:

this.BindFilter<MyAuthorizeFilter>(FilterScope.Controller, 0).WhenControllerHas<MyAuthorizeAttribute>(); 

參見:https://github.com/ninject/ninject.web.mvc/wiki/MVC3

與您的問題當前的實現是它作爲過濾器屬性發現一次,一次添加爲標準過濾器。其中一個用於這些實例將注入一個回購庫,另一個回購庫爲空。

注意:如果這可以簡化您的實現,則可以從現有的FilterAttribute派生。但在這種情況下不要將它用作屬性,而是將其用作普通過濾器。

+0

除了「注意」部分之外,所有都是有意義的。出於好奇,爲什麼當我將範圍更改爲操作而不是控制器時,它似乎工作正常? – 2011-04-06 21:15:20

+0

更改爲操作將改變您不再有控制器上的兩個過濾器,而是一個關於操作(具有repo引用)和一個關於控制器(repo == null)的操作。我不確定執行順序,以及.NET是否執行所有IAuthorizationFilters,或者直到成功。控制器上的一個仍然會導致NullRef異常。但可能它沒有執行。 – 2011-04-06 21:38:27

+0

感謝您的回答並跟進Remo – 2011-04-07 14:13:24

6

最好擴展AuthorizeAttribute類,以便授權對緩存的請求正確工作。您還需要使用Ninject.Web.Mvc

您將需要使用Ninject屬性注入來使用您的存儲庫。構造函數注入將不能使用屬性。

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    [Inject] 
    public IMyRepo MyRepo { get; set; } 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     return base.AuthorizeCore(httpContext); 
    } 
} 
+2

謝謝,這是我原來的,但後來開始接受一些「」底層提供商失敗打開「從EF例外......不知道,如果他們有關使用授權過濾器或不,所以我決定嘗試Ctor注入,並在這裏我是... – 2011-04-06 21:19:04

+0

嗨Rohan,只是要清楚。構造函數注入將無法正常工作,因爲在構造函數中我們傳遞屬性值(params數組)。此外,當您說屬性注入 - 屬性頂部的[Inject]屬性足以用Ninject來實現這一點嗎?你可以與Ninject綁定共享嗎?這是如何定義的。你是否需要在那裏指定輸入參數?我遇到類似實現的問題。在我的屬性中,我通過服務訪問dbcontext。我的dbcontext已經設置了InRequestScope,並且這樣做會拋出一個異常dbcontext正在處理。 – 2015-04-30 14:23:24

+0

,當我打開過濾器中的邏輯時,處理異常正在發生。 tps://github.com/ninject/Ninject.Web.Mvc/wiki/Filters-and-Scoped,但它對我來說沒有多大意義,究竟如何實現它..... – 2015-04-30 14:27:45

0

只是認爲我會在這裏添加我的解決方案似乎工作正常。

創建一個擴展AuthorizeAttribute並在構造函數中使用存儲庫接口的類。

這個類,然後覆蓋AuthorizeCore功能:

public class MyRoleAttribute : AuthorizeAttribute 
{ 
    private ICRepository repository; 

    public MyRoleAttribute(ICRepository Repo) 
    { 
     repository = Repo; 
    } 

protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     //Check if user authenticated 
     if (!httpContext.Request.IsAuthenticated) 
      return false; 

     //Can access items in the query string if needed 
     var id = (httpContext.Request.RequestContext.RouteData.Values["id"] as string) 
     ??(httpContext.Request["id"] as string); 

      //Can access repository that has been injected 
      if (repository.IsGroupCreator(.....)) 
      { 

       return true; 

      } 
      else 
      { 

       return false; 

      } 
    } 
} 

然後存儲庫注入到工作,我下面的代碼添加到MVC NinjectWebCommon.cs文件:

kernel.BindFilter<MyRoleAttribute>(FilterScope.Action, 0).When(
(controllerContext, actionDescriptor) => actionDescriptor.ActionName == "MyAction"); 

然後,這讓我來控制我需要的屬性和ninject需要處理庫注入的操作。希望這可以幫助某人。