假设我有一个控制器FooController
,它有一堆动作方法。我想覆盖其中一些方法,但没有一个方法被标记为virtual
,我不想更改FooController
的代码。
所以我实现了一个CustomFooController
(不是继承自FooController
)并编写我想要的方法的新版本。
现在我想首先路由到CustomFooController
,如果动作不可用,我想默认为FooController
。我已设置此路由配置以覆盖路由:
routes.MapRoute(
"customFoo",
"foo/{action}",
new { controller = "CustomFoo", action = UrlParameter.Optional }
);
以下是一些示例定义:
public class FooController : Controller
{
public ActionResult Bar { ... }
public ActionResult Baz { ... }
}
public class CustomFooController : Controller
{
public ActionResult Bar { ... }
}
因此,当访问/Foo/Bar
时,我们应该击中CustomFooController.Bar()
,当访问/Foo/Baz
时,我们应该击中FooController.Baz()
,因为Baz()
没有在CustomFooController
中实现。
但我得到“资源无法找到”,我理解为什么,但我可以以某种方式解决它而不修改FooController
?
你可能想看看HandleUnknownAction()(参见msdn reference page)。
当请求与控制器匹配时调用它,但在该控制器中找不到具有指定操作名称的方法。
因此,您可以在CustomFooController中重写该方法,以重定向到FooController中的相应操作(甚至基于您对请求相关数据的自定义检查的其他控制器)。
可以使用RedirectToAction()完成重定向(请参阅msdn reference page)
我想我自己找到了一个简洁的解决方案。由于我不想修改FooController
和其他应用程序的其他控制器,我正在扩展(并依赖于更新)我决定在我的启动MapMvcAttributeRoutes()
中使用来自System.Web.Mvc.RouteCollectionAttributeRoutingExtensions
的扩展方法RouteConfig
,以便首先匹配路由属性例如我的CustomFooController
优先于传统路由。
为了安全起见:HandleUnknownAction()仅在CustomFooController中实现。您不必修改FooController(或其他控制器)。