You can use the AsyncControllerActionInvoker class to do this, but since the method you need is protected, you need to first inherit the class and redefine the method as 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);
}
}
Then it is just a matter of using the same 2 objects you had before to call the new method.
var controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
var actionSelector = new ActionSelector();
var actionDescriptor =
actionSelector.FindAction(controllerContext, controllerDescriptor, actionName) ??
controllerDescriptor.GetCanonicalActions().FirstOrDefault(a => a.ActionName == actionName);
Note that this will work for both StandardRouteMethods and DirectRouteMethods.
However, one thing to be aware of is that calling this method will reset the RouteData for the controllerContext.RouteData and controllerContext.RequestContext.RouteData properties to that of the action that is found. So, you will need to wrap the ControllerContext and RequestContext classes and re-implement the RouteData properties so the setter has no effect if it is important that you don't destroy your context.
Reference: https://aspnetwebstack.codeplex.com/workitem/1989