【发布时间】:2016-06-06 13:34:01
【问题描述】:
我目前正在处理一个 MVC 项目,我正在尝试弄清楚如何在一个区域内扩展现有控制器的路由,特别是从另一个项目。
例如,我有一个控制器,其区域如下所示:
namespace MyProject.Areas.Foo.Controllers
{
[Authorize]
public class FooController : ApplicationController
{
//code
}
}
我想做的是能够在一个单独的项目中定义另一个控制器,可以像这样扩展它:
namespace MyOtherProject.Areas.Foo.Custom.Controllers
{
public class FooController : ApplicationController
{
public string Bar()
{
return "Bar";
}
}
}
基本上,我希望控制器几乎可以像使用 partial 关键字一样运行(这样我就可以调用原始或新的任何操作)。
主要问题
我真正想要完成的是,我有一个包含多个区域的主项目和包含各种客户端文件夹的解决方案的另一个区域。我希望能够从本质上扩展我的主项目的基本控制器,并在这些客户端文件夹中添加特定于客户端的操作,以便它们可以在主项目中使用。我已经用某些 MVC 视图来做这件事,但我希望我也能用控制器来完成它。
我的尝试
- 我尝试在类的两个声明中使用
partial关键字,但由于它们位于不同的项目/程序集中,我认为这不起作用。 - 我定义了一个构建事件,它将自定义 DLL 移动到主 MVC 项目的
bin目录中,但这似乎没有按预期工作。 - 我尝试了各种继承方法,希望新类能够被采用,但这些方法不起作用(收到重复的控制器声明错误)。
- 我读过有关尝试使用自定义
ControllerFactory的文章,但我不确定如何实现它。 - 我已尝试在 AreaRegistration 部分定义自定义命名空间路由参数以获取新控制器,如下例所示。
路由示例(AreaRegistration)
context.MapRoute(
AreaName,
String.Format("{0}/{{action}}/{{id}}", AreaName),
new { controller = AreaName, action = "Index", id = UrlParameter.Optional },
new[] {
String.Format("MyProject.Areas.{0}.Controllers", AreaName),
String.Format("MyOtherProject.Areas.{0}.Custom.Controllers", AreaName)
}
);
更新
根据 cmets 的一些讨论,我尝试了一种方法 seen here,其中涉及通过继承简单地处理这个问题:
// Main Project
namespace MyProject.Areas.Foo.Controllers
{
[Authorize]
public class FooController : ApplicationController
{
public ActionResult Index()
{
return View();
}
}
}
// This is in another project / namespace / assembly
namespace MyOtherProject.Foo.Controllers
{
public class CustomFooController : MyProject.Areas.Foo.Controllers.FooController
{
[Route("Foo/Bar")]
public string Bar()
{
return "Bar";
}
}
}
所以我目前的步骤如下:
- 从另一个项目/解决方案的主项目中的基础
FooController继承。 - 设置属性路由以访问自定义控制器,以避免来自主项目的路由冲突。
- 创建了一个构建事件,在从新的自定义项目构建时将自定义 DLL 移动到主项目中(以便可以访问)。
这似乎没有任何区别。我尝试访问Foo/Bar url,但它只是抛出了一个 404,就好像它根本没有看到它一样。 CustomFooController.cs 文件在它自己的单独项目中,只是一个类文件而不是 MVC 项目。它是否正确?需要在主项目中设置路由规则吗?
【问题讨论】:
-
使用继承有什么问题?在 project-B 中,包含对 project-main 的引用,然后 controller-B 从 controller-main 继承。或者,使用公共类作为基础并相应地配置您的路线。
-
所以我应该从项目 A 中的
FooController继承我的项目 B 控制器吗?如果是这样,这将如何影响我的路由,因为我希望能够使用相同的基本路由,即Foo/ProjectAAction或Foo/ProjectBAction。那还能用吗? -
所有到控制器 B 的路由也将获得控制器主操作,因为它们通过继承成为控制器 B 的一部分。即你的路由不会知道项目主控制器
-
这里我只使用属性路由。您的主要问题是试图强制控制器和操作名称以适应默认的
/controller/action路由约定。使用属性路由,您可以随心所欲地制作路由,而控制器/动作名称不再重要。 -
谢谢克里斯。仅继承就足够了吗?我尝试使用像this Gist 这样的方法,但我不知道这是否足够?我在构建时使用构建事件将该自定义 Project-B DLL 放置到适当的目录中,所以我应该能够去
Foo/Bar访问它,对吗?Foo/Index和第一个中的其他所有内容都应该有效吗?
标签: c# asp.net asp.net-mvc