24

가 Asp.net MVC의 URL 구조ASP.NET MVC에서 동적 컨트롤러 및 동작 방법을 얻는 방법은 무엇입니까?

http://example.com/ 제어기 {} 각각 "제어기"옵션/{동작}/{ID}

말할 http://example.com/blog 같이 진행하는 BlogController있다.

URL의 my {controller} 부분은 미리 결정되지 않았지만 런타임에 동적으로 결정됩니다. 컨트롤러를 기반으로 동일한 컨트롤러에 아무 것도 매핑하는 "동적 컨트롤러"를 어떻게 만듭니 까? 가치를 결정하고 무엇을 할 것인가?

{action}과 (와) 같은 일, 내 URL의 {action} 부분도 동적 인 경우이 시나리오를 프로그래밍 할 수있는 방법이 있습니까?

답변

23

물론입니다! 사용자 지정 컨트롤러가없는 경우 찾아서 DefaultControllerFactory을 재정의해야합니다. 그런 다음 동적 액션 이름을 처리하려면 IActionInvoker을 작성해야합니다. 당신이 코드 here의 더 많은 것을 볼 수 있습니다

public class DynamicActionInvoker : ControllerActionInvoker 
{ 
    private readonly IServiceLocator _Locator; 

    public DynamicActionInvoker(IServiceLocator locator) 
    { 
     _Locator = locator; 
    } 

    protected override ActionDescriptor FindAction(ControllerContext controllerContext, 
                ControllerDescriptor controllerDescriptor, string actionName) 
    { 
      // try to match an existing action name first 
     var action = base.FindAction(controllerContext, controllerDescriptor, actionName); 
     if (action != null) 
     { 
      return action; 
     } 

// @ray247 The remainder of this you'd probably write on your own... 
     var actionFinders = _Locator.GetAllInstances<IFindAction>(); 
     if (actionFinders == null) 
     { 
      return null; 
     } 

     return actionFinders 
      .Select(f => f.FindAction(controllerContext, controllerDescriptor, actionName)) 
      .Where(d => d != null) 
      .FirstOrDefault(); 
    } 
} 

: 같은

public class DynamicControllerFactory : DefaultControllerFactory 
{ 
    private readonly IServiceLocator _Locator; 

    public DynamicControllerFactory(IServiceLocator locator) 
    { 
     _Locator = locator; 
    } 

    protected override Type GetControllerType(string controllerName) 
    { 
     var controllerType = base.GetControllerType(controllerName); 
      // if a controller wasn't found with a matching name, return our dynamic controller 
     return controllerType ?? typeof (DynamicController); 
    } 

    protected override IController GetControllerInstance(Type controllerType) 
    { 
     var controller = base.GetControllerInstance(controllerType) as Controller; 

     var actionInvoker = _Locator.GetInstance<IActionInvoker>(); 
     if (actionInvoker != null) 
     { 
      controller.ActionInvoker = actionInvoker; 
     } 

     return controller; 
    } 
} 

그런 다음 액션 호출자은 다음과 같습니다

컨트롤러 공장과 같을 것입니다. 그것은 나 자신과 동료가 완전히 동적 인 MVC 파이프 라인을 작성하는 데 사용한 낡은 첫 번째 초안 시도입니다. 참조로 사용하고 원하는 것을 복사 할 수 있습니다.

편집 내가 그 코드가 무엇을하는지에 대한 몇 가지 배경을 포함해야한다 생각. 우리는 도메인 모델을 중심으로 MVC 계층을 동적으로 구축하려고했습니다. 따라서 도메인에 Product 클래스가있는 경우 products\alls으로 이동하면 모든 제품의 목록을 볼 수 있습니다. 제품을 추가하려면 product\add으로 이동하십시오. 제품을 편집하려면 product\edit\1을 방문하십시오. 우리는 엔티티의 속성을 편집 할 수 있도록하는 등의 작업을 시도했습니다. 그래서 product\editprice\1?value=42은 product # 1의 price 속성을 42로 설정합니다. (내 경로가 조금 벗어 났을 수 있으며 정확한 구문을 더 이상 기억할 수 없습니다.) 도움이 되었기를 바랍니다.

+0

안녕하세요 @Ryan이있을 것이다 기본/동적 컨트롤러에서 다음

routes.MapRoute("Dynamic", "{controller}/{command}/{id}", new { action = "ProcessCommand" }); 

: 난 당신이 같은 경로를 정의 할 수 있습니다 생각합니다. DynamicControllerFactory 및 DynamicActionInvoker를 https://github.com/ryanohs/DynamicServices에서 구현하려고 시도했습니다. 런타임 중에 DynamicControllerFactory 1st의 기본 생성자를 요청 받았습니다. 그런 다음 빈 구현을 추가했습니다. 그러나 parameterize 생성자는 호출되지 않으며 _locater 값은 절대로 설정되지 않습니다. 그래서 GetControllerInstance를 호출하는 동안 actionInvoker가 null _locator로 인해 설정되지 않았습니다. 내가 어디에서 잘못했는지._locator의 기본값을 지정해야하거나 다른 곳에서 런타임 중에 설정해야합니다. – mesimplybj

+1

동적 컨트롤러와 동적 액션 호출자가 필요할 때 누구나 시나리오를 자세히 설명 할 수 있습니까? – Thomas

1

IControllerFactory (또는 아마도 DefaultControllerFactory에서 파생 됨)을 작성한 다음 ControllerBuilder으로 등록해야합니다.

7

조금 더 반영한 후에는 다른 대답보다 동적 동작 이름을 처리하는 데 약간 간단한 방법이있을 수 있습니다. 그래도 기본 컨트롤러 팩토리를 재정의해야합니다. 당신이

public ActionResult ProcessCommand(string command, int id) 
{ 
    switch(command) 
    { 
     // whatever. 
    } 
} 
+0

동적 컨트롤러는 어떻습니까? –

관련 문제