9

ActionDescriptor속성 라우팅을 사용하는 컨트롤러에 대한 작업을 얻으려고 시도하지만 항상 null입니다. 내 연구에서 속성 라우팅을 사용할 때 Mvc 5 컨트롤러의 ActionDescriptor를 얻으려면 어떻게해야합니까?

var controllerDescriptor = new ReflectedControllerDescriptor(controllerType); 
var actionDescriptor = 
    controllerDescriptor.FindAction(controllerContext, actionName) ?? 
    controllerDescriptor.GetCanonicalActions().FirstOrDefault(a => a.ActionName == actionName); 

, 나는 당신이 그것을 줄 컨트롤러에있는 모든 방법을 분할 PopulateLookupTables라는 메소드가 클래스에 를 ActionMethodSelectorBase 것으로 나타났습니다. Thie 메서드 안에는 MethodInfo의 목록이 2 세트의 목록으로 필터링됩니다.

  • AliasedMethods - ActionNameSelectorAttribute로 장식되어 직접적인 경로와 모든 액션 메소드.
  • NonAliasedMethods - ActionNameSelectorAttribute로 장식되지 않은 직접 경로가없는 모든 동작 방법.

참고 : 컨트롤러 수준에서 직접 경로 (RouteAttribute)가 설정된 경우 AliasedMethods 및 NonAliasedMethods는 비어 있습니다.

참고 : 직접 루트는 컨트롤러 (제외 생성자 및 이벤트)에 있고 IRouteInfoProvider 또는 IDirectRouteFactory (RouteAttribute이 모두 상속) 중 하나에서 상속 속성으로 장식되어 방법으로 정의됩니다.

  • DirectRouteMethods - 직접 장식 IRouteInfoProvider의 형태와 방법.
  • 표준 루팅 메소드 - 직접 IRouteInfoProvider가없는 메소드. (RouteAttribute가있는 컨트롤러의 작업 메서드를 포함하지만 메서드에 RouteAttribute가없는 경우). ReflectedControllerDescriptor.FindAction가 호출

, 그것은 내부적으로 만 AliasedMethods과 (직접 루트로 모든 작업을 제외) NonAliasedMethods에 보이는 ActionMethodSelectorBase.FindActionMethods를 호출합니다. ReflectedControllerDescriptor.GetCanonicalActions가 호출

는 내부적으로 만 (직접 루트로 모든 작업을 exlude)에 AliasedMethodsNonAliasedMethods에 보이는 ReflectedControllerDescriptor.GetAllActionMethodsFromSelector 호출합니다. 내가 무엇을 볼 수에서

,는 한 곳에서 사용되는 DirectRouteMethods의 RouteCollection.MapMvcAttributeRoutes 확장자 방법. 즉, 경로 표가 있음을 의미합니다.경로 컬렉션에는 RouteCollectionRoute이 있지만 그 방법을 알 수는 없습니다.

사람은 RouteAttribute이있는 행동에 대한 ActionDescriptor을 얻는 방법을 알고 있나요

답변

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); 
    } 
} 

그런 다음 새로운 메소드를 호출하기 위해 이전에 가지고 있던 것과 동일한 두 개의 객체를 사용하면됩니다.

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가 아무런 영향을 미치지 않도록해야합니다.

참조 : https://aspnetwebstack.codeplex.com/workitem/1989

관련 문제