Custom AuthorizeAttribute Ninject Property Injection doesn't work (nested property has helper services that need to be inserted)
I think the specifics of my question are very different from other similar questions I have.
I know that when I have a custom AuthorizeAttribute I cannot inject dependencies with the constructor. This is because the constructor will take parameters - in my case, permission strings.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class UserAllCSPermissionBasedAuthFilter : AuthorizeAttribute
{
I am depending on the authorization service, so I am injected using property injection.
[Inject]
public IAuthorizationService _authorizationService { get; set; }
The problem is that this service depends on another service - serviceervice, which is directly related to the repository and dbcontext. I am specifying that my db context is in request scope. This throws out the exception - "The operation could not be completed because the DbContext was deleted." When I looked at the code, this happens when the authorization service calls the user service which asks the dbcontext for some data. How can I avoid this?
public class AuthorizationService : IAuthorizationService
{
private readonly ICommonRepository _commonRepository;
private readonly IRepositoryBase<UsersInRolesEntity> _repositoryUsersInRoles;
private readonly IRepositoryBase<UserCustomerRolesEntity> _repositoryCurstomerRoleEntities;
private readonly ISqlCustomersRepository _sqlCustomerRepository;
private readonly IRoleService _roleService;
private readonly IUserService _userService;
private readonly IPermissionService _permissionService;
public AuthorizationService(
IRepositoryBase<UsersInRolesEntity> repositoryUsersInRoles,
IRepositoryBase<UserCustomerRolesEntity> repositoryCurstomerRoleEntities,
ICommonRepository commonRepository,
ISqlCustomersRepository sqlCustomerRepository,
IRoleService roleService,
IUserService userService,
IPermissionService permissionService
)
{
source to share
Stephen thanks for your support, I looked at the articles you suggested and Ninject's guide. I totally agree with you that Property Binding is not a bad idea. But it was not possible to understand why we are doing everything in the article ( https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=98 ). I believe this was written before the Ninject authors added a way to configure attribute binding using their framework ( https://github.com/ninject/Ninject.Web.Mvc/wiki/Filter-configurations ).
I looked at my Ninject config. For my authorization filters, I had something like this:
#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
I have a couple of these and then the light bulb moment came :) I just saw a small error in my configuration. Instead of using:
kernel.BindFilter<UserAllCSPermissionBasedAuthFilter>(FilterScope.Controller, 0)
.WhenActionMethodHas<UserAllCSPermissionBasedAuthFilter>()
.WithConstructorArgumentFromControllerAttribute<UserAllCSPermissionBasedAuthFilter>("permissionEnums", att => att.PermissionEnums);
It should be:
kernel.BindFilter<UserAllCSPermissionBasedAuthFilter>(FilterScope.Controller, 0)
.WhenControllerHas<UserAllCSPermissionBasedAuthFilter>()
.WithConstructorArgumentFromControllerAttribute<UserAllCSPermissionBasedAuthFilter>("permissionEnums", att => att.PermissionEnums);
WhenActionMethodHas → WhenControllerHas.
This miraculously fixed everything. Works fine now and the code looks fine to me with no additional encoding changes.
source to share