Получить список настраиваемых атрибутов для текущего действия/контроллера в ASP.NET MVC

Проверка примера кода с http://lukesampson.com/post/471548689/entering-and-exiting-https-with-asp-net-mvc, написанный для ASP.NET MVC2, я заметил, что они могут проверять, применяется ли настраиваемый атрибут к текущему действию или контроллеру. путем доступа к filterContext.ActionDescriptor и filterContext.ActionDescriptor.ControllerDescriptor соответственно:

public class ExitHttpsIfNotRequiredAttribute : FilterAttribute, IAuthorizationFilter {
    public void OnAuthorization(AuthorizationContext filterContext) {
        // snip

        // abort if a [RequireHttps] attribute is applied to controller or action
        if(filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Length > 0) return;
        if(filterContext.ActionDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Length > 0) return;

        // snip
    }
}

Каким будет метод ASP.NET MVC 1 для проверки действия и контроллера на наличие настраиваемого атрибута? В ASP.NET MVC 1 нет filterContext.ActionDescriptor, что я могу сказать.


person DavGarcia    schedule 25.08.2010    source источник


Ответы (5)


Еще лучший и более надежный* подход:

filterContext.ActionDescriptor.GetCustomAttributes(
    typeof(RequireHttpsAttribute), true).Count> 0

Хотя это может быть только MVC 3.0+.

person Sunday Ironfoot    schedule 02.12.2012
comment
Это, кажется, не делает то же самое. Я попробовал это с атрибутом на контроллере, и это вернуло false. Однако использование кода из исходного вопроса работает нормально. - person David Omid; 27.07.2015
comment
Использование обоих вместе очень хорошо работает в MVC 4 if (filterContext.Controller.GetType().GetCustomAttributes(typeof(SkipLocationFilterAttribute), true).Any()) { return; } if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(SkipLocationFilterAttribute), false).Any()) { return; } - person PvtVandals; 08.10.2015
comment
@PvtVandals Я искал место, где можно разместить ваше позолоченное издание (я получил его самостоятельно), tada - person Ruben Bartelink; 23.01.2016

Позолоченное издание, работает на MVC5, возможно, 4/3:

filterContext.HasMarkerAttribute<RequireHttpsAttribute>()

Использует этот набор вспомогательных расширений:

public static class MarkerAttributeExtensions
{
    public static bool HasMarkerAttribute<T>(this AuthorizationContext that) {
        return that.Controller.HasMarkerAttribute<T>()
            || that.ActionDescriptor.HasMarkerAttribute<T>();
    }

    public static bool HasMarkerAttribute<T>(this ActionExecutingContext that) {
        return that.Controller.HasMarkerAttribute<T>()
            || that.ActionDescriptor.HasMarkerAttribute<T>();
    }

    public static bool HasMarkerAttribute<T>(this ControllerBase that) {
        return that.GetType().HasMarkerAttribute<T>();
    }

    public static bool HasMarkerAttribute<T>(this Type that) {
        return that.IsDefined(typeof(T), false);
    }

    public static IEnumerable<T> GetCustomAttributes<T>(this Type that) {
        return that.GetCustomAttributes(typeof(T), false).Cast<T>();
    }

    public static bool HasMarkerAttribute<T>(this ActionDescriptor that) {
        return that.IsDefined(typeof(T), false);
    }

    public static IEnumerable<T> GetCustomAttributes<T>(this ActionDescriptor that) {
        return that.GetCustomAttributes(typeof(T), false).Cast<T>();
    }
}
person Ruben Bartelink    schedule 22.01.2016
comment
Спасибо за публикацию! - person agrath; 05.05.2016
comment
Для всех, кто читает это, вы можете изменить AuthorizationContext на ActionExecutingContext, чтобы эти методы расширения работали с обычными ActionFilterAttribute - person elexis; 23.05.2016
comment
замените =› на return и сделайте тело функции: D - person Kasparov92; 30.07.2016
comment
@Kasparov92 :( Это действительный C # 6, и теперь его намного сложнее читать, IMO (раньше у меня было много запутанного пути). Уборка ... (Да, крепление Java очень уродливо - мы надеемся, что люди перейдут на C # 6 [и принятие участников с выраженным телом] как можно скорее) - person Ruben Bartelink; 31.07.2016
comment
Для тех, кто ищет, нажмите «Отредактировано» и перейдите к версии 4, если вам нужна версия членов выражения С# 6;) - person Ruben Bartelink; 29.06.2017

Кажется, это работает... есть ли лучший/более правильный способ в ASP.NET MVC 1?

if (filterContext.Controller.GetType().GetCustomAttributes(typeof(RequireHttpsAttribute), true).Length > 0)
    return;
string action = (string)filterContext.RouteData.Values["action"];
if (!string.IsNullOrEmpty(action) && filterContext.Controller.GetType().GetMethod(action).GetCustomAttributes(typeof(RequireHttpsAttribute), true).Length > 0)
    return;
person DavGarcia    schedule 25.08.2010
comment
Мне нужно знать - что делают эти возвраты? Почему ты только что вернулся? - person muttley91; 07.10.2015
comment
Вы можете видеть в исходном коде вопроса, что этот фрагмент находится внутри метода public void OnAuthorization атрибута. Если RequireHttpsAttribute находится в текущем контроллере или действии, то лучше всего «вернуться» из метода и продолжить работу, как будто ничего не произошло. Но если RequireHttps НЕ находится на контроллере или в действии, тогда он выполнит некоторый код, в этом случае, вероятно, перенаправив браузер на протокол, отличный от HTTPS. - person DavGarcia; 08.10.2015
comment
Обратите внимание, что этот фрагмент был для ASP.NET MVC 1 и, возможно, MVC 2. Начиная с MVC 3, были лучшие способы решения проблемы проверки существования контроллера и фильтров действий, как указал Сандей Айронфут. - person DavGarcia; 08.10.2015
comment
Да, я заметил ответ MVC3+ после публикации моего комментария, и это сработало для меня. - person muttley91; 08.10.2015

это сработало для меня в .NET Core 2.2:

var controllerActionDescriptor = actionContext.ActionDescriptor as ControllerActionDescriptor;

if (controllerActionDescriptor != null)
{
    // Check if the attribute exists on the action method
    if (controllerActionDescriptor.MethodInfo?.GetCustomAttributes(inherit: true)?.Any(a => a.GetType().Equals(typeof(CustomAttribute))) ?? false)
        return true;

    // Check if the attribute exists on the controller
    if (controllerActionDescriptor.ControllerTypeInfo?.GetCustomAttributes(typeof(CustomAttribute), true)?.Any() ?? false)
        return true;
}
person lisandro101    schedule 22.11.2019
comment
Мне интересно, почему нет способа получить все настраиваемые атрибуты для действия, в том числе унаследованные от контроллера. - person Johan Maes; 26.05.2020

Я использую MVC5, и мне пришлось использовать следующее для проверки внутри класса, который наследуется от ActionFilterAttribute и реализует IAuthenticationFilter.

If filterContext.ActionDescriptor.GetCustomAttributes(GetType(RequireHttpsAttribute), True).Any() OrElse filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(GetType(RequireHttpsAttribute), True).Any() Then
' .. the given attribute is present ..
End If

Я не мог заставить решение Рубена работать на меня, но, вероятно, это было из-за того, что я напортачил при преобразовании с C# на VB.

person Drew    schedule 31.05.2019