Ninject Custom AuthorizeAttribute Injection isn't working
-
21-04-2021 - |
سؤال
I've hit a bit of a wall and was hoping someone could point out where I'm going wrong.
I've been using Ninject to Inject into custom ActionFilterAttributes and this is working fine:
kernel.BindFilter<CriticalErrorAttribute>(FilterScope.Last, 1);
I'm now trying to inject into a custom AuthorizeAttribute. I've got the syntax correct so that I'm inserting the Role and custom attributes:
kernel.BindFilter<Authorisation>(FilterScope.Action, 0)
.WhenActionMethodHas<Authorisation>()
.WithPropertyValueFromActionAttribute<Authorisation>("Roles", n => n.Roles)
.WithPropertyValueFromActionAttribute<Authorisation>("Years", n => n.Years);
The attribute is being executed correctly and the roles and years are being inserted fine, my issue is that a service I'm trying to inject in is always null:
[Inject]
public IUserServices userService { get; set; }
In normal ActionFilterAttributes the service is injected fine, but here it isn't.
Any help would be appreciated
المحلول
Instead of deriving from an attribute you should implement the corresponding interface e.g. IAuthorizationFilter
or IActionFilter
and use a different normal attribut to mark the controllers or actions for which you want to apply that filter
public class AuthorisationFilter : IAuthorizationFilter ....
public class Authorization : Attribute ....
kernel.BindFilter<AuthorisationFilter>(FilterScope.Action, 0)
.WhenActionMethodHas<Authorisation>()
.WithPropertyValueFromActionAttribute<Authorisation>("Roles", n => n.Roles)
.WithPropertyValueFromActionAttribute<Authorisation>("Years", n => n.Years);
نصائح أخرى
I have very issue similar to the already asked question, but I can't solve it. I am adding my custom authorization filters, which inside have access to the db context. The dbcontext is defined to be used InRequestScope (Ninject Binding). When I hit the point where the filter is executing I am getting an error that dbcontext is already been disposed.
void IAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext)
{
....
var customerPermissions = _authorizationService.GetCustomersListForPermission(_userProvider.CurrentUser.Username,
this.PermissionEnums);
..
}
The aurhorization service asks the db for permissions for the current user - this means that Ninject should create a new dbcontext instance, but this dosn't happen... I read that "The MVC framework itsself caches filters. " https://github.com/ninject/Ninject.Web.Mvc/wiki/Filters-and-Scoped
But can't get how to implement my filter bindings.
Currently these are the bindings that I have:
kernel.Bind<TDBContext>().ToSelf().InRequestScope();
kernel.Bind<IUnitOfWork>().To<UnitOfWork>();//.InThreadScope();
kernel.Bind<IUnitOfWorkManager>().To<UnitOfWorkManager>().InRequestScope();
#region UserAllCSPermissionBasedAuthFilter
kernel.BindFilter<UserAllCSPermissionBasedAuthFilter>(FilterScope.Action, 0)
.WhenActionMethodHas<UserAllCSPermissionBasedAuthFilter>()
.WithConstructorArgumentFromActionAttribute<UserAllCSPermissionBasedAuthFilter>("permissionEnums", att => att.PermissionEnums);
kernel.BindFilter<UserAllCSPermissionBasedAuthFilter>(FilterScope.Controller, 0)
.WhenActionMethodHas<UserAllCSPermissionBasedAuthFilter>()
.WithConstructorArgumentFromControllerAttribute<UserAllCSPermissionBasedAuthFilter>("permissionEnums", att => att.PermissionEnums);
#endregion
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class UserAllCSPermissionBasedAuthFilter : FilterAttribute, IAuthorizationFilter
{
#region Private Fields
private static readonly ObjectCache _permissionCache = MemoryCache.Default;
private static readonly ILog _log = LogManager.GetLogger(typeof(UserAllCSPermissionBasedAuthFilter));
[Inject]
public IAuthorizationService _authorizationService { get; set; }/// DependencyResolver.Current.GetService<IAuthorizationService>();