我有一个自定义授权类,它继承自FilterAttribute并实现IAuthorizationFilter。我正在使用最新版本的Ninject w / asp.net MVC 3支持。
我遇到的问题是我使用构造函数注入来注入存储库。但是在调用OnAuthorization时,存储库为null。这是代码......
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: 我已经确认,如果我将过滤器范围更改为action,那么存储库可用OnAuthorization(非null)。
这可以在下面工作,但我需要在控制器范围,而不是行动。
this.BindFilter<MyAuthorizeAttribute >(System.Web.Mvc.FilterScope.Action, null).WhenActionMethodHas<MyAuthorizeAttribute >();
答案 0 :(得分:10)
属性不支持构造函数注入,因为它们是由.NET Framework创建的,并且不受Ninject的控制。如果你真的想使用FilterAttribute(我不推荐),你将不得不使用属性注入。
相反,继续你刚刚开始的。您需要一个实现IAuthorizationFilter的过滤器(不是从FilterAttribute派生,只是从上面的代码中删除它),另外还需要一个标记控制器/操作的普通属性。
然后更改绑定:
this.BindFilter<MyAuthorizeFilter>(FilterScope.Controller, 0).WhenControllerHas<MyAuthorizeAttribute>();
请参阅:https://github.com/ninject/ninject.web.mvc/wiki/MVC3
您当前实现的问题是,它被发现一次作为过滤器属性,并且一次添加为普通过滤器。对于这些实例,一个将注入repo,另一个repo为null。
注意:如果这样可以简化您的实现,则可以从现有的FilterAttribute派生。但是在这种情况下不要将它用作属性,而是将其用作普通过滤器。
答案 1 :(得分:6)
最好扩展AuthorizeAttribute类,以便授权可以正常使用缓存的请求。您还需要使用Ninject.Web.Mvc
您需要使用Ninject属性注入来使用您的存储库。构造函数注入不适用于Attributes。
public class MyAuthorizeAttribute : AuthorizeAttribute
{
[Inject]
public IMyRepo MyRepo { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return base.AuthorizeCore(httpContext);
}
}
答案 2 :(得分: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负责存储库注入。希望这有助于某人。