将ASP.NET MVC控制器放入单独的项目中

108

我正在学习asp.net mvc,试图找出如何将我的控制器移动到一个单独的项目中。通常情况下,在我以前设计asp.net web应用程序时,我会为我的模型创建一个项目,为逻辑创建另一个项目,然后是web。

现在,我希望遵循类似的模式,将模型和控制器分别放入自己的独立项目中,只将视图/脚本/css留在web中。模型部分很容易实现,但是我不明白如何使位于不同项目中的控制器被“找到”。而且,我想知道这是否可取。谢谢!

5个回答

92

首先,将你的模型放置在一个单独的项目中确实是一个好主意。正如你已经发现的那样,这很简单。

关于控制器和视图,对于大多数基础项目来说,我并没有看到将它们分开的明显优势,尽管在特定应用程序中可能有特别需要这样做的情况。

如果你选择这样做,则需要告诉框架如何找到你的控制器。最基本的方法是提供自己的ControllerFactory。你可以查看DefaultControllerFactory的源代码,了解如何完成这项任务。继承此类并覆盖GetControllerType(string controllerName)方法可能足以实现你所要求的功能。

一旦创建了自定义的ControllerFactory,你需要在global.asax的Application_Start中添加以下行,告诉框架在哪里找到它:

ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());

更新: 请阅读此文章 以及 其他相关文章获取更多信息。另外,请注意Phil Haack在该文章中的评论:

ControllerBuilder.Current.DefaultNamespaces.Add(
    "ExternalAssembly.Controllers");

这并不是一个完整的解决方案,但对于简单情况可能已经足够了。


2
谢谢Craig!这正是我一直在寻找的。这些信息甚至存在于网络上吗?我已经在Google上搜索了很久,但没有什么运气。StackOverflow再次帮忙了! - Aaron Palmer
13
我同意,控制器负责处理用户输入,操作模型,然后将数据传递给视图。它们通常非常特定于一个应用程序。任何不特定于该应用程序的逻辑可能更适合在库或模型中。但是总体上来说,控制器应该随着Web项目一起。 - Haacked
2
我有一个错误控制器和视图,在两个应用程序之间是相同的。对我来说,将它们放在一个单独的程序集中,让两个应用程序都可以使用,是有意义的。 - Sailing Judo
3
将控制器放在单独的项目中,这样测试控制器和使用控制反转会更容易——这将是主要原因。 - Samuel Goldenbaum
1
@Chev,我认为这没有任何区别。你的控制器的可测试性更多地取决于你如何编写它们,而不是它们所在的位置 - Craig Stuntz
显示剩余6条评论

20

虽然创建自己的ControllerFactory是合理的,但我发现在每个项目中定义所有的Controller并从我的共享项目中派生它们更方便:

namespace MyProject1.Controllers
{
   public class MyController : MySharedProject.Controllers.MyController
   {
      // nothing much to do here...
   }
}

namespace MySharedProject.Controllers
{
   public abstract class MyController : System.Web.Mvc.Controller
   {
      // all (or most) of my controller logic here...
   }
}

这样做的额外好处在于您有一个可以放置 Controller 逻辑的地方,这些逻辑因项目而异。此外,其他开发人员可以更容易地找到您的 Controller 逻辑,因为 Controllers 存在于标准位置。

至于是否建议这样做,我认为绝对是可以的。我已经创建了一些通用的帐户管理逻辑,希望在在业务逻辑非常不同的项目之间共享它们。因此,我分享了我的 Account 和 Admin Controllers,但其他 Controllers 则特定于其各自的项目。


1
这个很好地解决了问题,但我必须消除一些冗余代码以防止路由错误。 - Ken Mc
你好,我如何管理这种类型项目的路由?我想使用属性路由... - محمد
您可以像使用常规路由一样使用特性路由。 - ThisGuy
2
不确定为什么这个没有更多的赞...我认为比被接受的答案更优雅。谢谢! - jleach
我们需要做什么来为基础控制器生成Swagger文档? - nkigen
显示剩余3条评论

4
  • Add the Class Library for your mvc project.
  • In the class add the following code(For u'r Controller Code)

    namespace ContactController
    {
    public class ContactController : Controller
    {
        public ActionResult Call()
        {
            ViewBag.Title = "Inside MyFirst Controller.";
            return View();
        }
    }
    

    }

  • On the mvc project view folder add the folder for Contact and create a Call.cshtml file. View Folder

  • Add the class library project reference into your main MVC project.

参考

  • 最后将联系人控制器的命名空间引用到路由配置中。

路由配置


3
很不幸,你的命名空间与控制器名称相同。 - Mariusz Jamro

3

在我更新System.Web.Mvc NuGet引用以后,我的问题得到了解决,因此MvcWebsite和Class Library使用相同的System.Web.Mvc版本

无需添加默认命名空间


问题在于MvcWebsite没有抛出异常,而当前mvc程序集的版本低于类库所引用的mvc程序集。 - Homayoun Behzadian

1
我使用的最简单的分离形式是在原始MVC项目中保留Views,但删除Controllers。然后,在一个新的ClassLibrary项目中添加Controller类,并确保它们继承自Controller。
只要您正确地设置了引用和使用,MVC路由引擎将自动路由到ClassLibrary中的Controllers,而Controllers将自动从原始MVC项目构建Views。
我正在使用这种架构来实现一个可以与主解决方案分开编译和部署的Html报告模块。最后,我摆脱了SSRS!

终于我摆脱了SSRS。 - Richard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接