我试图在使用属性路由的控制器上获取 ActionDescriptor ,但它始终为null。
var controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
var actionDescriptor =
controllerDescriptor.FindAction(controllerContext, actionName) ??
controllerDescriptor.GetCanonicalActions().FirstOrDefault(a => a.ActionName == actionName);
从我的研究中,我发现在类 ActionMethodSelectorBase 中有一个名为 PopulateLookupTables 的方法,它会拆分你给它的控制器中的所有方法。在其中的方法中,它将MethodInfo的列表过滤为2组列表。
注意:如果在控制器级别设置了直接路由(RouteAttribute),则AliasedMethods和NonAliasedMethods将为空。
注意:直接路由被定义为控制器中的方法(不包括构造函数和事件),并使用继承自IRouteInfoProvider或IDirectRouteFactory的属性进行修饰(RouteAttribute继承自这两者)。
和
当调用 ReflectedControllerDescriptor.FindAction 时,它会在内部调用 ActionMethodSelectorBase.FindActionMethods ,它只会查看 AliasedMethods 和 NonAliasedMethods (不包括直接路由的所有操作)。
当调用 ReflectedControllerDescriptor.GetCanonicalActions 时,它会在内部调用 ReflectedControllerDescriptor.GetAllActionMethodsFromSelector ,它只会查看 AliasedMethods 和 NonAliasedMethods (排除直接路线的所有行动)。
从我所看到的, DirectRouteMethods 仅在一个地方使用,即 RouteCollection.MapMvcAttributeRoutes 扩展方法。这意味着 RouteTable.Routes 集合对操作有一个 RouteCollectionRoute ,但我不知道如何进行操作。
有没有人知道如何为 RouteAttribute
的操作获取 ActionDescriptor答案 0 :(得分:1)
您可以使用AsyncControllerActionInvoker类来执行此操作,但由于您需要的方法受到保护,因此您需要先继承该类并将该方法重新定义为public。
private class ActionSelector
: AsyncControllerActionInvoker
{
// Needed because FindAction is protected, and we are changing it to be public
public new ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)
{
return base.FindAction(controllerContext, controllerDescriptor, actionName);
}
}
然后,只需使用您之前使用的相同2个对象来调用新方法。
var controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
var actionSelector = new ActionSelector();
var actionDescriptor =
actionSelector.FindAction(controllerContext, controllerDescriptor, actionName) ??
controllerDescriptor.GetCanonicalActions().FirstOrDefault(a => a.ActionName == actionName);
请注意,这适用于StandardRouteMethods和DirectRouteMethods。
但是,有一点需要注意的是,调用此方法会将controllerContext.RouteData和controllerContext.RequestContext.RouteData属性的RouteData重置为找到的操作的属性。因此,您需要包装ControllerContext和RequestContext类并重新实现RouteData属性,这样如果重要的是不破坏上下文,则setter无效。