如何在 ASP.NET MVC 中实现动态控制器和动作方法? [英] How to achieve a dynamic controller and action method in ASP.NET MVC?
问题描述
在 Asp.net MVC 中,url 结构类似于
In Asp.net MVC the url structure goes like
http://example.com/{controller}/{action}/{id}
http://example.com/{controller}/{action}/{id}
对于每个控制器",比如 http://example.com/blog,都有一个 BlogController.
For each "controller", say http://example.com/blog, there is a BlogController.
但是我的 url 的 {controller} 部分不是预先决定的,而是在运行时动态确定的,我如何创建一个动态控制器",将任何东西映射到同一个控制器,然后基于值并决定做什么?
But my {controller} portion of the url is not decided pre-hand, but it is dynamically determined at run time, how do I create a "dynamic controller" that maps anything to the same controller which then based on the value and determines what to do?
与 {action} 相同,如果我的 url 的 {action} 部分也是动态的,有没有办法对这种情况进行编程?
Same thing with {action}, if the {action} portion of my url is also dynamic, is there a way to program this scenario?
推荐答案
当然可以!如果自定义控制器不存在,您需要覆盖 DefaultControllerFactory
以查找自定义控制器.然后您需要编写一个 IActionInvoker
来处理动态操作名称.
Absolutely! You'll need to override the DefaultControllerFactory
to find a custom controller if one doesn't exist. Then you'll need to write an IActionInvoker
to handle dynamic action names.
您的控制器工厂看起来像:
Your controller factory will look something like:
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;
}
}
那么你的动作调用者应该是这样的:
Then your action invoker would be like:
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();
}
}
您可以在此处查看更多此代码.这是我自己和一位同事在编写完全动态的 MVC 管道时的旧初稿尝试.您可以随意将其用作参考并复制您想要的内容.
You can see a lot more of this code here. It's an old first draft attempt by myself and a coworker at writing a fully dynamic MVC pipeline. You're free to use it as a reference and copy what you want.
编辑
我想我应该包括一些关于该代码的作用的背景知识.我们试图围绕域模型动态构建 MVC 层.因此,如果您的域包含 Product 类,您可以导航到 productsalls
以查看所有产品的列表.如果要添加产品,请导航到 productadd
.您可以转到 productedit1
来编辑产品.我们甚至尝试了诸如允许您编辑实体的属性之类的方法.所以 producteditprice1?value=42
会将产品 #1 的 price 属性设置为 42.(我的路径可能有点偏离,我已经记不起确切的语法了.)希望这有帮助!
I figured I should include some background about what that code does. We were trying to dynamically build the MVC layer around a domain model. So if your domain contained a Product class, you could navigate to productsalls
to see a list of all products. If you wanted to add a product, you'd navigate to productadd
. You could go to productedit1
to edit a product. We even tried things like allowing you to edit properties on an entity. So producteditprice1?value=42
would set the price property of product #1 to 42. (My paths might be a little off, I can't recall the exact syntax anymore.) Hope this helps!
这篇关于如何在 ASP.NET MVC 中实现动态控制器和动作方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!