Get custom attributes via ActionExecutingContext from controller .Net Core
Asked Answered
A

4

23

This used used to work with earlier version of .Net. What's the equivalent in .net core terms. Now I get following error:

'ActionDescriptor' does not contain a definition for 'GetCustomAttributes' and no extension method 'GetCustomAttributes' accepting a first argument of type 'ActionDescriptor' could be found

public virtual void SetupMetadata(ActionExecutingContext filterContext)
{
    var myAttr = filterContext.ActionDescriptor.GetCustomAttributes(typeof(MyAttribute), false);
    if (myAttr.Length == 1)
        //do something
}

Attribute definition:

public class MyAttribute : Attribute
{
    private readonly string _parameter;

    public PageTitleAttribute(string parameter)
    {
        _parameter = parameter;
    }

    public string Parameter { get { return _parameter; } }
}

Code Usage:

[MyAttribute("Attribute value is set here")]
public ActionResult About()
{
    ViewBag.Message = "Your application description page.";
    return View();
}
Alake answered 23/1, 2017 at 9:55 Comment(0)
A
32

Hope to help others, here's what i did:

var attrib = (filterContext.ActionDescriptor as ControllerActionDescriptor).MethodInfo.GetCustomAttributes<MyAttribute>().FirstOrDefault();
Alake answered 23/1, 2017 at 10:25 Comment(1)
For those looking to do the same for a parameter: cast a ControllerActionDescriptor.Parameters to ControllerParameterDescriptor which has a ParameterInfo for all the usual reflection information.Mickel
G
15

Another option without needing a runtime cast:

public class MyAttribute :  Microsoft.AspNetCore.Mvc.Filters.ActionFilterAttribute {
  // same content as in the question
}

By inheriting from ActionFilterAttribute, your attribute will now appear in the ActionDescriptor.FilterDescriptors collection, and you can search that:

public virtual void SetupMetadata(ActionExecutingContext filterContext)
{
    var myAttr = filterContext.ActionDescriptor
        .FilterDescriptors
        .Where(x => x.Filter is MyAttribute)
        .ToArray();
    if (myAttr.Length == 1) {
        //do something
    }
}

I'm unsure if this is dirtier or cleaner than casting to ControllerActionDescriptor, but it's an option if you control the attribute.

Grainger answered 20/2, 2018 at 23:6 Comment(1)
A more direct way could be bool isAttributeSet = filterContext.ActionDescriptor.FilterDescriptors.Any(fd => fd.Filter is MyAttribute);Emogene
I
9

For ASP.NET Core 3+:

    var filters = context.Filters;
    // And filter it like this: 
    var filtered = filters.OfType<OurFilterType>();

Intercurrent answered 3/6, 2020 at 0:10 Comment(0)
M
3

Why not use:

filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(MyAttribute), false).Any()
Mask answered 27/1, 2020 at 11:46 Comment(1)
This just gets controller's attributes not action's attributes.Panchromatic

© 2022 - 2024 — McMap. All rights reserved.