Найдите атрибуты для действия из ViewEngine в ASP.NET MVC - PullRequest
1 голос
/ 20 мая 2009

У меня есть собственный ViewEngine, и я хочу изменить используемую главную страницу в зависимости от того, имеет ли запрошенное действие фильтр атрибута Authorize.

Пока я просто использую отражение следующим образом:

var method = controllerContext.Controller.GetType().GetMethod(viewName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
if (method != null)
{
    if (method.GetCustomAttributes(typeof(AuthorizeAttribute), true).Length > 0)
    {
        masterName = "Admin.master";
    }
}

Но я не большой поклонник использования рефлексии для повторяющихся задач. Я знаю, что могу использовать кеш представления для ускорения работы после первого раза, но мне интересно, есть ли более прямой способ получить доступ к списку фильтров, примененных к действию, внутри метода FindView метода ViewEngine

1 Ответ

1 голос
/ 02 ноября 2009

Вы в значительной степени ограничены использованием отражения для получения любой информации об атрибутах независимо от чего-либо, включая методы действий MVC. ;)

Единственный другой способ получить эту информацию - пройти через пути ControllerDescriptor

В вашем случае вы могли бы вообще пропустить поиск атрибута authorize и просто спросить, авторизован ли пользователь или нет, и предоставить ему необходимую ему главную страницу.

Ранее я настраивал главную страницу динамически в пользовательском механизме просмотра, и наиболее эффективный вариант - просмотреть любую доступную информацию HttpContextBase. Для одного сценария я просто передал параметры запроса или добавил параметры маршрута {masterPage}, когда мне нужно их использовать.

Единственный другой путь к информации о действии - это маршрут ReflectedControllerDescriptor. Проблема этого метода в том, что он очень многословен и требует много строк кода, чтобы делать то, что вы делаете.

Вот небольшой фрагмент кода (который я нашел в stackoverflow!) Этого метода «дескриптора» для выполнения обрезки ссылок безопасности. Этот код также можно использовать для динамической установки главной страницы, если она была в пользовательском механизме просмотра. Это не то, что вы ищете, но может помочь кому-то другому выполнить такую ​​же настройку динамической мастер-страницы где-нибудь еще:

    public static bool HasActionPermission( this HtmlHelper htmlHelper, string actionName, string controllerName )
    {
        //if the controller name is empty the ASP.NET convention is:
        //"we are linking to a different controller
        ControllerBase controllerToLinkTo = string.IsNullOrEmpty(controllerName) 
                                                ? htmlHelper.ViewContext.Controller
                                                : GetControllerByName(htmlHelper, controllerName);

        var controllerContext = new ControllerContext(htmlHelper.ViewContext.RequestContext, controllerToLinkTo);

        var controllerDescriptor = new ReflectedControllerDescriptor(controllerToLinkTo.GetType());

        var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);

        return ActionIsAuthorized(controllerContext, actionDescriptor);
    }


    private static bool ActionIsAuthorized(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        if (actionDescriptor == null)
            return false; // action does not exist so say yes - should we authorise this?!

        AuthorizationContext authContext = new AuthorizationContext(controllerContext);

        // run each auth filter until on fails
        // performance could be improved by some caching
        foreach (IAuthorizationFilter authFilter in actionDescriptor.GetFilters().AuthorizationFilters)
        {
            authFilter.OnAuthorization(authContext);

            if (authContext.Result != null)
                return false;
        }

        return true;
    }
...