2015-04-30 2 views
3

Я думаю, что особенности моего вопроса сильно отличаются от других подобных вопросов, которые у меня есть.Custom AuthorizeAttribute Ninject Property Injection не работает (вложенное свойство имеет вспомогательные сервисы, которые необходимо ввести)

Я знаю, что когда у меня есть пользовательский атрибут AuthorizeAttribute, я не могу вставлять зависимости с конструктором. Это связано с тем, что конструктор примет параметры - в моем случае - строки прав доступа.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] 
    public class UserAllCSPermissionBasedAuthFilter : AuthorizeAttribute 
    { 

Я в зависимости от службы авторизации, поэтому меня вводят с использованием инъекции свойств.

[Inject] 
    public IAuthorizationService _authorizationService { get; set; } 

Проблема в том, что эта услуга зависит от другой службы - обслуживания пользователей, которая напрямую связана с репозиторием и dbcontext. У меня есть указание, чтобы мой контекст db находился в области запроса. Это исключение - «Операция не может быть завершена, потому что DbContext был удален». Когда я посмотрел на код, это происходит, когда служба авторизации вызывает службу пользователей, которая запрашивает dbcontext для некоторых данных. Как избежать этого?

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 
      ) 
     { 
+0

Должен ли я использовать условные привязки Ninject в моем случае? Или я сделал что-то неправильно? –

+0

Предотвратите впрыскивание зависимостей в ваши атрибуты, как описано [здесь] (https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=98) и [здесь] (http: //blog.ploeh .dk/2014/06/13/пассивные-атрибуты /). – Steven

+0

Спасибо за ссылки, я думаю, они полезны, но мне сложно переварить их. Автор говорит: «Проблема с этим подходом заключается в том, что экземпляры атрибутов создаются во время выполнения, поэтому вы не можете использовать правильные шаблоны зависимостей зависимостей (DI), такие как инжекция конструктора. Если атрибут определяет поведение (что многие из Атрибуты веб-API), наиболее распространенной попыткой написания слабосвязанного кода является обращение к статическому локатору сервисов (анти-шаблон). " то его решение «определяет атрибуты без поведения».В его решении я не вижу, как при выполнении фильтра –

ответ

0

Steven, спасибо за поддержку, я смотрел статьи, которые вы предложили, и руководство Ninject. Я полностью согласен с вами в том, что Property Binding - неплохая идея. Но не удалось понять, почему мы делаем все, что в статье (https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=98). Я полагаю, что это было написано до того, как авторы Ninject добавили способ настройки привязки атрибутов с использованием их фреймворка (https://github.com/ninject/Ninject.Web.Mvc/wiki/Filter-configurations).

Я взглянул на свою конфигурацию Ninject. Для моих фильтров авторизации у меня было что-то вроде этого:

#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 

У меня есть несколько из них, а затем в тот момент свет лампы пришел :) Я просто увидел небольшую ошибку в моей конфигурации. Вместо использования:

kernel.BindFilter<UserAllCSPermissionBasedAuthFilter>(FilterScope.Controller, 0) 
    .WhenActionMethodHas<UserAllCSPermissionBasedAuthFilter>() 
    .WithConstructorArgumentFromControllerAttribute<UserAllCSPermissionBasedAuthFilter>("permissionEnums", att => att.PermissionEnums); 

Это должно быть на самом деле:

kernel.BindFilter<UserAllCSPermissionBasedAuthFilter>(FilterScope.Controller, 0) 
    .WhenControllerHas<UserAllCSPermissionBasedAuthFilter>() 
    .WithConstructorArgumentFromControllerAttribute<UserAllCSPermissionBasedAuthFilter>("permissionEnums", att => att.PermissionEnums); 

WhenActionMethodHas -> WhenControllerHas.

Это чудом исправлено все. Теперь работает отлично, и код выглядит отлично для меня без дополнительных изменений в кодировке.

Смежные вопросы