Asp.net-Mvc-2

如何在 ASP.NET MVC 中實現動態控制器和動作方法?

  • July 21, 2010

在 Asp.net MVC 中,url 結構如下

<http://example.com/> {controller}/{action}/{id}

對於每個“控制器”,比如<http://example.com/blog>,都有一個 BlogController。

但是我的 url 的 {controller} 部分不是預先決定的,而是在執行時動態確定的,我如何創建一個“動態控制器”,將任何東西映射到同一個控制器,然後根據值並確定什麼去做?

{action} 也是一樣,如果我的 url 的 {action} 部分也是動態的,有沒有辦法對這種情況進行程式?

絕對地!DefaultControllerFactory如果自定義控制器不存在,您將需要覆蓋以查找自定義控制器。然後你需要編寫一個IActionInvoker來處理動態動作名稱。

您的控制器工廠將如下所示:

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&lt;IActionInvoker&gt;();
       if (actionInvoker != null)
       {
           controller.ActionInvoker = actionInvoker;
       }

       return controller;
   }
}

那麼你的動作呼叫者會是這樣的:

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&lt;IFindAction&gt;();
       if (actionFinders == null)
       {
           return null;
       }

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

您可以在此處看到更多此程式碼。這是我和一位同事編寫完全動態 MVC 管道的舊初稿嘗試。您可以隨意將其用作參考並複制您想要的內容。

編輯

我想我應該包括一些關於該程式碼作用的背景。我們試圖圍繞域模型動態建構 MVC 層。因此,如果您的域包含 Product 類,您可以導航到products\alls查看所有產品的列表。如果您想添加產品,請導航至product\add. 你可以去product\edit\1編輯一個產品。我們甚至嘗試過允許您編輯實體上的屬性之類的方法。因此product\editprice\1?value=42將產品 #1 的價格屬性設置為 42。(我的路徑可能有點偏離,我不記得確切的語法了。)希望這會有所幫助!

引用自:https://stackoverflow.com/questions/3303801