24

Trong Asp.net MVC cấu trúc url đi như thếLàm thế nào để đạt được một bộ điều khiển động và phương pháp hành động trong ASP.NET MVC?

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

Đối với mỗi "điều khiển", nói http://example.com/blog, có một BlogController.

Nhưng phần {controller} của url không được xác định trước, nhưng được xác định động trong thời gian chạy, làm cách nào để tạo "bộ điều khiển động" ánh xạ mọi thứ tới cùng một bộ điều khiển, sau đó dựa trên giá trị và xác định phải làm gì?

Điều tương tự với {action}, nếu phần {action} của url của tôi cũng là động, có cách nào để lập trình kịch bản này không?

Trả lời

23

Tuyệt đối! Bạn sẽ cần ghi đè số DefaultControllerFactory để tìm bộ điều khiển tùy chỉnh nếu không tồn tại. Sau đó, bạn sẽ cần phải viết một IActionInvoker để xử lý tên hành động động.

máy điều khiển của bạn sẽ giống như thế:

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

Sau đó, Invoker hành động của bạn sẽ như thế nào:

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

Bạn có thể thấy rất nhiều các mã này here. Đó là một nỗ lực dự thảo đầu tiên cũ của bản thân tôi và một đồng nghiệp tại viết một đường ống MVC đầy đủ năng động. Bạn được tự do sử dụng nó như là một tài liệu tham khảo và sao chép những gì bạn muốn.

Sửa

tôi figured tôi nên bao gồm một số nền tảng về những gì mã nào. Chúng tôi đã cố gắng xây dựng động lớp MVC xung quanh một mô hình miền. Vì vậy, nếu miền của bạn có chứa một lớp Sản phẩm, bạn có thể điều hướng đến products\alls để xem danh sách tất cả các sản phẩm. Nếu bạn muốn thêm sản phẩm, bạn sẽ điều hướng đến product\add. Bạn có thể truy cập product\edit\1 để chỉnh sửa sản phẩm. Chúng tôi thậm chí đã thử những thứ như cho phép bạn chỉnh sửa các thuộc tính trên một thực thể. Vì vậy, product\editprice\1?value=42 sẽ đặt thuộc tính giá của sản phẩm # 1 thành 42. (Đường dẫn của tôi có thể hơi lệch, tôi không thể nhớ cú pháp chính xác nữa.) Hy vọng điều này sẽ hữu ích!

+0

Xin chào @Ryan. Tôi đã cố gắng để thực hiện DynamicControllerFactory của bạn và DynamicActionInvoker từ https://github.com/ryanohs/DynamicServices. Thời gian chạy tôi đã được yêu cầu cho constructor mặc định của DynamicControllerFactory 1. Sau đó, tôi thêm một với thực hiện sản phẩm nào. Nhưng constructer parameterize không bao giờ được gọi và giá trị _locater không bao giờ được thiết lập. Vì vậy, trong khi gọi GetControllerInstance actionInvoker không được thiết lập do null _locator. nơi tôi đã làm sai.Tôi cần phải cung cấp cho giá trị mặc định cho _locator, hoặc nó được thiết lập thiết lập trong thời gian chạy từ nơi khác – mesimplybj

+1

bất cứ ai có thể xây dựng kịch bản khi điều khiển động và invoker hành động năng động sẽ được yêu cầu? – Thomas

1

Bạn cần phải tự viết IControllerFactory (hoặc có thể lấy từ DefaultControllerFactory) và sau đó đăng ký nó với ControllerBuilder.

7

Sau một chút phản ánh, có thể có cách đơn giản hơn một chút để bạn xử lý tên hành động động hơn câu trả lời khác của tôi. Bạn vẫn sẽ cần phải ghi đè lên nhà máy bộ điều khiển mặc định. Tôi nghĩ bạn có thể xác định lộ trình của bạn như:

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

Sau đó, trên mặc định điều khiển của bạn/động bạn phải

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

Làm thế nào về bộ điều khiển động? –

Các vấn đề liên quan