Get list of custom attributes for current action/controller in ASP.NET MVC
Solution 1
This seems to work... is there a better / more proper way in 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;
Solution 2
Even better and more reliable* approach:
filterContext.ActionDescriptor.GetCustomAttributes(
typeof(RequireHttpsAttribute), true).Count> 0
Though this might be MVC 3.0+ only.
Solution 3
Goldplated edition, works on MVC5, probably 4/3:
filterContext.HasMarkerAttribute<RequireHttpsAttribute>()
Uses this set of helper extensions:
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>();
}
}
Solution 4
this worked for me in .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;
}
Solution 5
I'm using MVC5 and had to use the following to check from within a class that inherits from ActionFilterAttribute and implements 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
I couldn't get Ruben's solution to work for me but it was probably because I messed up in the conversion from C# to VB.
Related videos on Youtube
nuthan ratnam vara
Web programmer with a background in usability.
Updated on July 09, 2022Comments
-
nuthan ratnam vara almost 2 years
Checking out the sample code from http://lukesampson.com/post/471548689/entering-and-exiting-https-with-asp-net-mvc written for ASP.NET MVC2, I noticed they can check if a custom attribute is applied to the current action or controller by accessing
filterContext.ActionDescriptor
andfilterContext.ActionDescriptor.ControllerDescriptor
respectively: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 } }
What would be the ASP.NET MVC 1 method of checking the action and controller for a custom attribute? In ASP.NET MVC 1 there is no
filterContext.ActionDescriptor
that I can tell. -
David Omid almost 9 yearsThis doesn't seem to do the same thing. I tried this with an attribute on the controller and this returned false. Using the code from the original question works fine though.
-
muttley91 over 8 yearsI need to know - what do these returns do? Why are you just returning?
-
nuthan ratnam vara over 8 yearsYou can see in the original code in the question that this snippet is inside of an attribute's "public void OnAuthorization" method. If the RequireHttpsAttribute is on the current controller or action, then the best thing to do is the 'return' out of the method and continuing on like nothing happened. But if RequireHttps is NOT on the controller or action then it will execute some code, in this case probably redirecting the browser to a non-HTTPS protocol.
-
nuthan ratnam vara over 8 yearsNote that this snippet was for ASP.NET MVC 1, and maybe MVC 2. Since MVC 3, there have been better ways to deal with the issue of checking for the existence of controller and action filters as Sunday Ironfoot pointed out.
-
PvtVandals over 8 yearsUsing both together work very well in MVC 4
if (filterContext.Controller.GetType().GetCustomAttributes(typeof(SkipLocationFilterAttribute), true).Any()) { return; } if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(SkipLocationFilterAttribute), false).Any()) { return; }
-
muttley91 over 8 yearsYes I noticed the MVC3+ answer after posting my comment, and it worked for me.
-
Raymond over 8 years@PvtVandals I was looking for somewhere to put a goldplated edition of yours (I independently derived), tada
-
agrath almost 8 yearsThank you for posting this!
-
elexis almost 8 yearsFor anyone who reads this, you can change
AuthorizationContext
toActionExecutingContext
to make these extension methods work with regularActionFilterAttribute
s -
Kasparov92 almost 8 yearsreplace => with return and make the function body :D
-
Raymond almost 8 years@Kasparov92 :( Its valid C#6 and is way harder to read now IMO (I had it the long winded way before). Tidying... (Yes, the Java bracing is extremely ugly - here's hoping people move to C#6 [and acceptance of expression bodied members] ASAP)
-
Raymond almost 7 yearsFor anyone looking, click on edited and go to version 4 if you want a C#6 expression bodied members version ;)
-
Johan Maes almost 4 yearsI'm wondering why there isn't a method to get all the custom attributes for an action, including those inherited from the controller.