Asp.net mvc 获取ASP.NET MVC中当前操作/控制器的自定义属性列表

Asp.net mvc 获取ASP.NET MVC中当前操作/控制器的自定义属性列表,asp.net-mvc,custom-attributes,authorize-attribute,Asp.net Mvc,Custom Attributes,Authorize Attribute,查看为ASP.NET MVC2编写的示例代码时,我注意到他们可以通过分别访问filterContext.ActionDescriptor和filterContext.ActionDescriptor.ControllerDescriptor来检查自定义属性是否应用于当前操作或控制器: public class ExitHttpsIfNotRequiredAttribute : FilterAttribute, IAuthorizationFilter { public void OnAu

查看为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

这似乎有效。。。在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;

更好、更可靠的*方法:

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

虽然这可能只是MVC 3.0+版本。

镀金版,适用于MVC5,可能是4/3:

filterContext.HasMarkerAttribute<RequireHttpsAttribute>()
filterContext.HasMarkerAttribute()
使用以下辅助对象扩展集:

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>();
    }
}
公共静态类标记TributionExtensions
{
公共静态bool HasMarkerAttribute(此授权上下文){
返回该.Controller.HasMarkerAttribute()
||HasMarkerAttribute();
}
公共静态bool HasMarkerAttribute(此ActionExecutingContext为){
返回该.Controller.HasMarkerAttribute()
||HasMarkerAttribute();
}
public static bool HasMarkerAttribute(此控制器的基础是){
返回该.GetType().HasMarkeraAttribute();
}
公共静态bool HasMarkerAttribute(该类型){
返回.IsDefined(typeof(T),false);
}
公共静态IEnumerable GetCustomAttributes(该类型){
返回.GetCustomAttributes(typeof(T),false).Cast();
}
公共静态bool HasMarkerAttribute(此ActionDescriptor表示){
返回.IsDefined(typeof(T),false);
}
公共静态IEnumerable GetCustomAttributes(此ActionDescriptor用于){
返回.GetCustomAttributes(typeof(T),false).Cast();
}
}

我使用的是MVC5,必须在继承ActionFilterAttribute并实现IAAuthenticationFilter的类中使用以下内容进行检查

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的转换过程中出错了。

这在.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;
}

这似乎不是一回事。我在控制器上尝试了这个属性,结果返回false。不过,使用原始问题中的代码可以很好地工作。在MVC4
if(filterContext.Controller.GetType().GetCustomAttributes(typeof(SkipLocationFilterAttribute),true)。Any(){return;}if(filterContext.ActionDescriptor.GetCustomAttributes(typeof(SkipLocationFilterAttribute),false)中,两者结合使用效果非常好.Any()){return;}
@PvtVandals我在找地方放你的镀金版(我独立派生),我需要知道-这些返回做什么?为什么要返回?您可以在问题的原始代码中看到,此代码段位于属性的“public void on authorization”方法中。如果requireHttpAttribute位于当前控制器或操作上,那么最好的方法是“返回”方法并继续,就像什么都没有发生一样。但是,如果控制器或操作上没有RequireHttps,则它将执行一些代码,在这种情况下,可能会将浏览器重定向到非HTTPS协议。请注意,此代码段适用于ASP.NET MVC 1,也可能是MVC 2。自MVC 3以来,正如Sunday Ironfoot所指出的,有更好的方法来处理检查控制器和动作过滤器是否存在的问题。是的,我在发布我的评论后注意到了MVC3+的答案,这对我很有效。感谢您发布此消息!对于阅读本文的任何人,您可以将
AuthorizationContext
更改为
ActionExecutingContext
,使这些扩展方法与常规
ActionFilterAttribute
sreplace=>一起使用,并使函数体:D@Kasparov92:(它是有效的C#6,现在更难读了(我以前有过冗长的经历)整理…(是的,Java支撑非常难看-这里希望人们尽快迁移到C#6[和接受表达式体成员])对于任何人,如果你想要C#6表达式体成员版本,请单击编辑并转到版本4)我想知道为什么没有一个方法来获取动作的所有自定义属性,包括从控制器继承的属性。