Подтвердить что ты не робот

Атрибут привязки Ninject к фильтру с аргументами конструктора

Я читал столько ответов, сколько мог, но они, похоже, не соответствуют одной детали.

Проблема заключается в привязке фильтра действий (с сервисом, который вводится контроллером) к соответствующему атрибуту, мне не удалось выяснить, как передать значения параметра/свойства из атрибута в связанный фильтр. Ниже приведен код, а ниже - мой поддельный код:

Фильтр и атрибут

public class AuthorizationFilter : IAuthorizationFilter
{
    private readonly IAuthorizationService _authorizationService;
    private readonly UserRoles _requiredRoles;   // Enum

    public AuthorizationFilter(IAuthorizationService authorizationService, UserRoles requiredRoles)
    {
        _authorizationService = authorizationService;
        _requiredRoles = requiredRoles;
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Session == null)
            HandleUnauthorizedRequest(filterContext);
        else {
            var authorized = _authorizationService.IsUserInRole((UserSessionInfoViewModel) filterContext.HttpContext.Session["user"], _requiredRoles);
            if (!authorized)
                HandleUnauthorizedRequest(filterContext);
            // else TODO: deal with cache... 
        }
    }
}

public class RequireRolesAttribute : FilterAttribute
{
    public readonly UserRoles RequiredRoles;

    public RequireRolesAttribute(UserRoles requiredRoles)
    {
        RequiredRoles = requiredRoles;
    }        
}

Связывание фильтра/атрибута

kernel.BindFilter<AuthorizationFilter>(FilterScope.Controller, 0)
      .WhenControllerHas<RequireRolesAttribute>();
kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0)
      .WhenActionMethodHas<RequireRolesAttribute>();

Это должно гарантировать, что любой контроллер/действие, украшенное [RolesRequired], привязано к фильтру. Все идет нормально. Теперь я хочу объявить через атрибут роли (подобно запасу AuthorizeAttribute) и передать эти значения на фильтр, который фактически выполняет авторизацию.

Предполагаемый/Поддельный код:

[RequireRoles(UserRoles.Author)]
public ActionResult Index()
{
    // blah
}

В частности,

Что нужно, чтобы сообщить AuthorizationFilter о ролях? Может ли фильтр /ninject получить доступ к аргументам, переданным конструктору атрибута? Может ли фильтр /ninject вытащить их из общедоступного свойства атрибутов?

Для справки, эти статьи были огромной помощью, но не отвечают на это:

Инъекция зависимостей с атрибутом Ninject и Filter для asp.net mvc

Пользовательская авторизация MVC 3 и Ninject IoC

B Z, Remo Gloor, другие... как я могу это сделать?

4b9b3361

Ответ 1

Я понял это (благодаря указаниям и документации Remo).

Используйте соответствующее расширение .WithConstructorArgument, являетесь ли вы привязкой к фильтру Controller или Action. Например, привязка моего фильтра действий выглядит следующим образом:

kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0)
      .WhenActionMethodHas<RequireRolesAttribute>()
      .WithConstructorArgumentFromActionAttribute<RequireRolesAttribute>("requiredRoles", o => o.RequiredRoles);

Как только я понял подпись Func < > , все стало ясно. Лучшим способом, который я нашел для этого, было

  • сделать тип расширения для моего атрибута

    .WithConstructorArgumentFromActionAttribute<TAttribute>()
    
  • выберите значение из объекта обратного вызова (ваш атрибут) через lambda:

    ("argumentName", o => o.PropertyName)
    

Ответ 2

и принести метод расширения BindFilter в область не забудьте добавить;

using Ninject.Web.Mvc.FilterBindingSyntax;