How to read action method's attributes in ASP.NET Core MVC?

后端 未结 5 1734
日久生厌
日久生厌 2020-12-08 12:43

Based on this article I\'m trying to create an IActionFilter implementation for ASP.NET Core that can process attributes that are marked on the controller and t

相关标签:
5条回答
  • 2020-12-08 13:28

    As answered by Henk Mollena

    public void OnActionExecuting(ActionExecutingContext context) { var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor; if (controllerActionDescriptor != null) { var controllerAttributes = controllerActionDescriptor .MethodInfo .GetCustomAttributes(inherit: true); } }

    is the correct way if you want to check the presence of an attribute applied to an action.

    I just want to add to his answer in case if you want to check the presence of an attribute applied to the controller

    public void OnActionExecuting(ActionExecutingContext context)
    {
        var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
        if (controllerActionDescriptor != null)
        {
            var actionAttributes = controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes(inherit: true);
        }
    }
    

    Also you can use the overloaded function of the GetCustomAttributes functions to get your specific attribute(s)

    var specificAttribute = GetCustomAttributes(typeof(YourSpecificAttribute), true).FirstOrDefault()

    0 讨论(0)
  • 2020-12-08 13:29

    You can access the MethodInfo of the action through the ControllerActionDescriptor class:

    public void OnActionExecuting(ActionExecutingContext context)
    {
        if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
        {
            var actionAttributes = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true);
        }
    }
    

    The MVC 5 ActionDescriptor class used to implement the ICustomAttributeProvider interface which gave access to the attributes. For some reason this was removed in the ASP.NET Core MVC ActionDescriptor class.

    0 讨论(0)
  • 2020-12-08 13:40

    I created an extension method that mimics the original GetCustomAttributes based in Henk Mollema's solution.

        public static IEnumerable<T> GetCustomAttributes<T>(this Microsoft.AspNet.Mvc.Abstractions.ActionDescriptor actionDescriptor) where T : Attribute
        {
            var controllerActionDescriptor = actionDescriptor as ControllerActionDescriptor;
            if (controllerActionDescriptor != null)
            {
                return controllerActionDescriptor.MethodInfo.GetCustomAttributes<T>();
            }
    
            return Enumerable.Empty<T>();
        }
    

    Hope it helps.

    0 讨论(0)
  • 2020-12-08 13:42

    My custom attribute is inherit from ActionFilterAttribute. I put it on my controller but there is one action do not need it. I want to use AllowAnonymous attribute to ignore that but it not work. So I add this snippet in my custom attribute to find the AllowAnonymous and skip it. You can get other in the for loop.

        public class PermissionAttribute : ActionFilterAttribute
        {
            public override void OnActionExecuting(ActionExecutingContext context)
            {
                foreach (var filterDescriptors in context.ActionDescriptor.FilterDescriptors)
                {
                    if (filterDescriptors.Filter.GetType() == typeof(AllowAnonymousFilter))
                    {
                        return;
                    }
                }
            }
        }
    
    0 讨论(0)
  • 2020-12-08 13:47

    Invoking GetCustomAttributes on a method and/or class is slow(er). You should not invoke GetCustomAttributes every request since .net core 2.2, which @Henk Mollema is suggesting. (There is one exception which I will explain later)

    Instead, on application startup time, the asp.net core framework will invoke GetCustomAttributes on the action method and controller for you and store the result in the EndPoint metadata.

    You can then access this metadata in your asp.net core filters via the EndpointMetadata property of the ActionDescriptor class.

    public class CustomFilter : IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context)
        {
            // Get attributes on the executing action method and it's defining controller class
            var attributes = context.ActionDescriptor.EndpointMetadata.OfType<MyCustomAttribute>();
        }
    
        public void OnActionExecuted(ActionExecutedContext context)
        {
        }
    }
    

    If you do not have access to the ActionDescriptor (for example: because you are operating from a Middleware instead of an filter) from asp.net core 3.0 you can use the GetEndpoint extension method to access it's Metadata. For more info see this github issue.

    public class CustomMiddleware
    {
        private readonly RequestDelegate next;
    
        public CustomMiddleware(RequestDelegate next)
        {
            this.next = next;
        }
    
        public async Task Invoke(HttpContext context)
        {
            // Get the enpoint which is executing (asp.net core 3.0 only)
            var executingEnpoint = context.GetEndpoint();
    
            // Get attributes on the executing action method and it's defining controller class
            var attributes = executingEnpoint.Metadata.OfType<MyCustomAttribute>();
    
            await next(context);
    
            // Get the enpoint which was executed (asp.net core 2.2 possible after call to await next(context))
            var executingEnpoint2 = context.GetEndpoint();
    
            // Get attributes on the executing action method and it's defining controller class
            var attributes2 = executingEnpoint.Metadata.OfType<MyCustomAttribute>();
        }
    }
    

    Like stated above, Endpoint Metadata contains the attributes for the action method and its defining controller class. This means that if you would want to explicitly IGNORE the attributes applied on either the controller class or the action method, you have to use GetCustomAttributes. This is almost never the case in asp.net core.

    0 讨论(0)
提交回复
热议问题