MVC3: группировка фильтров действий или вызов фильтров действий из других фильтров действий

Я пытаюсь написать класс атрибутов, который можно использовать во всех моих «админских» действиях, который затем эффективно применяет все соответствующие фильтры действий/авторизации к этому действию. Например, я всегда применяю AuthoriseAttribute и пользовательский AdminLayoutAttribute, поэтому я намерен просто иметь AdminAttribute, который каким-то образом подразумевает оба вышеперечисленных. Таким образом, я могу вносить изменения во весь раздел администратора в одном удобном месте.

Однако я не понимаю, как я могу это сделать. Может кто-то указать мне верное направление?

Очень признателен.


person hofnarwillie    schedule 12.12.2012    source источник


Ответы (1)


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

[Authorize]
[AdminLayout]
public AdminController: Controller
{
    //action methods
}

Наличие атрибута, сочетающего авторизацию и некоторую пользовательскую логику макета, может рассматриваться как нарушение принципа единой ответственности, но если у вас нет другого выбора, вы можете попробовать следующие подходы:

Если вы хотите заменить существующий AdminLayoutAttribute новым AdminAttribute, вы можете создать AdminAttribute, чтобы он наследовал стандартный AuthorizeAttribute, а также реализовывал IActionFilter\IResultFilter, как в вашем пользовательском атрибуте AdminLayoutAttribute.

public class AdminLayoutAttribute: AuthorizeAttribute, IActionFilter, IResultFilter
{
    //Logic as in existing AdminLayoutAttribute to be replaced
}

В противном случае, если вы хотите сохранить существующий AdminLayoutAttribute и добавить новый AdminAttribute, который объединяет его с AuthorizeAttribute, вы можете затем наследовать свой настраиваемый атрибут и реализовать IAuthorizationFilter, вызвав внутренний экземпляр типа AuthorizationFilter.

public class AdminLayoutAttribute: AdminLayoutAttribute, IAuthorizationFilter
{
    //Implement IAuthorizationFilter by delegating to an internal AuthorizeFilter instance
    private _authorizeFilter = new AuthorizeAttribute();

    public override object TypeId 
    { 
        //override from base Attribute class as in AuthorizeAttribute class
        get { return _authorizeFilter.TypeId ; }
    }

    public string Roles 
    {
        get { return _authorizeFilter.Roles; }
        set { _authorizeFilter.Roles = value; }
    }

    public string Users 
    {
        get { return _authorizeFilter.Users; }
        set { _authorizeFilter.Users = value; }
    }

    public void OnAuthorization(AuthorizationContext filterContext) 
    {
        _authorizeFilter.OnAuthorization(filterContext);
    }

}

Ключевым моментом в обоих вариантах является отсутствие нового класса AdminAttribute, наследуемого от двух конкретных классов, поскольку множественное наследование не поддерживается C#.

person Daniel J.G.    schedule 12.12.2012
comment
Даниил, спасибо, попробую. - person hofnarwillie; 13.12.2012