Ray*_*Ray 26 asp.net-mvc-routing asp.net-mvc-controller asp.net-mvc-2
在Asp.net MVC中,网址结构如下
http://example.com/ {controller}/{action}/{id}
对于每个"控制器",比如http://example.com/blog,都有一个BlogController.
但是我的{controller}部分的url不是预先决定的,但它是在运行时动态确定的,我如何创建一个"动态控制器",将任何东西映射到同一个控制器,然后根据该值确定什么去做?
与{action}相同,如果我的网址的{action}部分也是动态的,有没有办法对此方案进行编程?
Rya*_*yan 25
绝对!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<IActionInvoker>();
if (actionInvoker != null)
{
controller.ActionInvoker = actionInvoker;
}
return controller;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你的动作调用者就像:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在此处看到更多此代码.这是我自己和同事在编写一个完全动态的MVC管道时的初步尝试.您可以将其用作参考并复制您想要的内容.
编辑
我想我应该包含一些关于该代码的作用的背景知识.我们试图围绕域模型动态构建MVC层.因此,如果您的域包含Product类,您可以导航products\alls到查看所有产品的列表.如果您想添加产品,请导航至product\add.你可以去product\edit\1编辑一个产品.我们甚至尝试过允许您编辑实体属性的内容.所以product\editprice\1?value=42将产品#1的价格属性设置为42.(我的路径可能有点偏,我不记得确切的语法了.)希望这有帮助!
经过一点反思之后,处理动态动作名称可能比我的其他答案更简单一些.您仍然需要覆盖默认控制器工厂.我想你可以定义你的路线,如:
routes.MapRoute("Dynamic", "{controller}/{command}/{id}", new { action = "ProcessCommand" });
Run Code Online (Sandbox Code Playgroud)
然后在您的默认/动态控制器上
public ActionResult ProcessCommand(string command, int id)
{
switch(command)
{
// whatever.
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21479 次 |
| 最近记录: |