如何在 ASP.NET Core MVC 中读取操作方法的属性?
Posted
技术标签:
【中文标题】如何在 ASP.NET Core MVC 中读取操作方法的属性?【英文标题】:How to read action method's attributes in ASP.NET Core MVC? 【发布时间】:2015-08-07 09:47:53 【问题描述】:基于this article,我正在尝试为 ASP.NET Core 创建一个IActionFilter
实现,它可以处理控制器上标记的属性和控制器的操作。虽然读取控制器的属性很容易,但我无法找到读取动作方法上定义的属性的方法。
这是我现在拥有的代码:
public sealed class ActionFilterDispatcher : IActionFilter
private readonly Func<Type, IEnumerable> container;
public ActionFilterDispatcher(Func<Type, IEnumerable> container)
this.container = container;
public void OnActionExecuting(ActionExecutingContext context)
var attributes = context.Controller.GetType().GetCustomAttributes(true);
attributes = attributes.Append(/* how to read attributes from action method? */);
foreach (var attribute in attributes)
Type filterType = typeof(IActionFilter<>).MakeGenericType(attribute.GetType());
IEnumerable filters = this.container.Invoke(filterType);
foreach (dynamic actionFilter in filters)
actionFilter.OnActionExecuting((dynamic)attribute, context);
public void OnActionExecuted(ActionExecutedContext context)
throw new NotImplementedException();
我的问题是:如何在 ASP.NET Core MVC 中读取 action 方法的属性?
【问题讨论】:
你会得到MemberInfo
,不管你有兴趣使用反射API,然后使用GetCustomAttributes
。希望我没有误解这个问题
【参考方案1】:
您可以通过ControllerActionDescriptor
类访问动作的MethodInfo
:
public void OnActionExecuting(ActionExecutingContext context)
if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
var actionAttributes = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true);
MVC 5 ActionDescriptor
类用于实现ICustomAttributeProvider
接口,该接口可以访问属性。由于某种原因,这已在 ASP.NET Core MVC ActionDescriptor
类中删除。
【讨论】:
如何在 asp.net mvc 6 中做到这一点 这是关于 MVC 6(或 Core 1.0)的。 我的错我没看清楚。你能检查我的答案是否正确吗?我只是找到一种获取属性的方法并将其发布。 检查 controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes() 以获取已在控制器上设置的属性而不是方法也很有用。 您可以对此代码使用模式匹配:if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
【参考方案2】:
在方法和/或类上调用GetCustomAttributes
是慢(呃)。自 .net core 2.2 以来,您应该不调用GetCustomAttributes
的每个请求,@Henk Mollema 建议这样做。 (有一个例外,我稍后会解释)
相反,在应用程序启动时,asp.net 核心框架将为您调用操作方法和控制器上的GetCustomAttributes
,并将结果存储在EndPoint
metadata。
然后您可以通过ActionDescriptor
class 的EndpointMetadata
property 在您的asp.net 核心过滤器中访问此元数据。
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)
如果您无权访问ActionDescriptor
(例如:因为您使用的是中间件而不是过滤器)来自 asp.net core 3.0,您可以使用 GetEndpoint
extension method访问它是Metadata
。
有关更多信息,请参阅this github 问题。
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>();
如上所述,端点元数据包含操作方法及其定义控制器类的属性。这意味着如果您想显式地忽略应用于控制器类或操作方法的属性,则必须使用GetCustomAttributes
。这在 asp.net core 中几乎从来没有。
【讨论】:
如果您在 ASP.NET Core 3.0 或更高版本中使用端点路由,这应该是正确答案 很好的答案,我不得不升级到 3.1,但这是值得的。【参考方案3】:我的自定义属性继承自 ActionFilterAttribute。我把它放在我的控制器上,但有一个动作不需要它。我想使用AllowAnonymous
属性来忽略它,但它不起作用。所以我在我的自定义属性中添加了这个 sn-p 以找到 AllowAnonymous
并跳过它。您可以在 for 循环中获取其他内容。
public class PermissionAttribute : ActionFilterAttribute
public override void OnActionExecuting(ActionExecutingContext context)
foreach (var filterDescriptors in context.ActionDescriptor.FilterDescriptors)
if (filterDescriptors.Filter.GetType() == typeof(AllowAnonymousFilter))
return;
【讨论】:
FilterDescriptors
属性仅在您的自定义属性实际上是 MVC Filter 时才有效。如果您将自定义 passive attribute 应用于您的操作,那么显然您的解决方案将不起作用。【参考方案4】:
我基于 Henk Mollema 的解决方案创建了一个模仿原始 GetCustomAttributes
的扩展方法。
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>();
希望对你有帮助。
【讨论】:
与 NuGet 包 System.Reflection.Extensions 和使用到 System.Reflection 结合使用效果很好【参考方案5】:正如Henk Mollena所回答的那样
public void OnActionExecuting(ActionExecutingContext context)
var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
if (controllerActionDescriptor != null)
var controllerAttributes = controllerActionDescriptor
.MethodInfo
.GetCustomAttributes(inherit: true);
如果您想检查是否存在应用于操作的属性,这是正确的方法。
我只是想补充他的答案,以防您想检查是否存在 应用于控制器的属性
public void OnActionExecuting(ActionExecutingContext context)
var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
if (controllerActionDescriptor != null)
var actionAttributes = controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes(inherit: true);
您还可以使用 GetCustomAttributes 函数的重载函数来获取您的特定属性
var specificAttribute = GetCustomAttributes(typeof(YourSpecificAttribute), true).FirstOrDefault()
【讨论】:
以上是关于如何在 ASP.NET Core MVC 中读取操作方法的属性?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 asp net core 2.2 中间件中多次读取请求正文?
菜鸟入门ASP.NET Core5:命令行配置Json文件配置Bind读取配置到C#实例在Core Mvc中使用Options