当控制器类在不同的程序集中时,如何将Controller注册到ASP.NET MVC中?

我的目标是修改asp.net mvc的控制器注册表,以便我可以在单独的(子)程序集中创建控制器和视图,只需将View文件和DLL复制到主机MVC应用程序,新控制器就可以“插入” “到主机应用程序。

显然,我需要某种IoC模式,但我不知所措。

我的想法是引用一个带有system.web.mvc的子程序集,然后开始构建从Controllerinheritance的控制器类:

单独组装:

 using System.Web; using System.Web.Mvc; namespace ChildApp { public class ChildController : Controller { ActionResult Index() { return View(); } } } 

耶和华都很好。 但后来我考虑修改主机应用程序的Controller注册表以在运行时加载我的新子控制器,我感到困惑。 也许是因为我需要更深入地了解C#。

无论如何,我以为我需要创建一个CustomControllerFactory类。 所以我开始编写一个覆盖GetControllerInstance()方法的类。 在我打字时,intellisence突然出现:

主机MVC应用程序:

 public class CustomControllerFactory : DefaultControllerFactory { protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { return base.GetControllerInstance(requestContext, controllerType); } } 

现在,在这一点上,我很茫然。 我不知道那是做什么的。 最初,我打算像服务定位器一样编写一个“Controller Loader”类,如下所示:

主机MVC应用程序:

 public class ControllerLoader { public static IList Load(string folder) { IList controllers = new List(); // Get files in folder string[] files = Directory.GetFiles(folder, "*.plug.dll"); foreach(string file in files) { Assembly assembly = Assembly.LoadFile(file); var types = assembly.GetExportedTypes(); foreach (Type type in types) { if (type.GetInterfaces().Contains(typeof(IController))) { object instance = Activator.CreateInstance(type); controllers.Add(instance as IController); } } } return controllers; } } 

然后我计划使用我的控制器列表在控制器工厂中注册它们。 但是……怎么样? 我觉得我正处于搞清楚的边缘。 我想这一切都归结为这个问题:我如何挂钩return base.GetControllerInstance(requestContext, controllerType); ? 或者,我应该使用不同的方法吗?

从“根”ASP.NET MVC项目引用其他程序集。 如果控制器在另一个命名空间中,则需要修改global.asax中的路由,如下所示:

 public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, namespaces: new[] { typeof(HomeController).Namespace } ); } 

注意MapRoute方法的附加namespaces参数。

您的其他项目应该像某个区域一样设置,您将获得所需的结果。 区域注册课程将使您的区域项目融为一体。 然后,您可以将dll放入正在运行的应用程序中,它将在不构建整个应用程序并重新部署的情况下运行。

最简单的方法是在解决方案中添加一个新的mvc项目,让Visual Studio在/ areas / mynewprog /中创建新项目。 删除所有不需要的文件,并添加一个区域注册类来连接它。

构建项目,抓住它的dll并将其放入正在运行的网站bin目录中,并将其…

然后你只需处理视图和内容,或者将它们编译到dll中,或者将它们复制到服务器中的areas / mynewproj /文件夹中。

我对控制器的经验是,这才有效。 将程序集复制到bin目录中(或添加对程序集的引用,它将在那里复制)

我没有尝试过观点

创建一个单独的模块,如图所示插件项目结构:

插件项目结构

请注意,某些文件从项目中排除。

MessagingController.cs文件如下:

 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MessagingModule.Controllers { public class MessagingController : Controller { // // GET: /Messaging/ public ActionResult Index() { var appName = Session["appName"]; // Get some value from another module return Content("Yep Messaging module @"+ appName); } } } 

MessagingAreaRegistration文件如下所示:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web.Mvc; namespace MessagingModule { public class MessagingAreaRegistration : AreaRegistration { public override string AreaName { get { return "Messaging"; } } public override void RegisterArea( AreaRegistrationContext context ) { context.MapRoute( "Messaging_default", "Messaging/{controller}/{action}/{id}", new { action = "Index", id = UrlParameter.Optional } //new[] { "MessagingModule.Controllers" } ); } } } 

Global.asax.cs文件的相关部分如下:

[将外部插件(控制器,api控制器库)加载到当前应用程序域中。 在此之后,asp.net mvc为您完成剩余的工作(区域注册和控制器发现)[3]

  using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; using System.Reflection; using System.Web.Configuration; using System.Text.RegularExpressions; namespace mvcapp { // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { var domain = AppDomain.CurrentDomain; domain.Load("MessagingModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");