Как зарегистрировать контроллер в ASP.NET MVC, когда класс контроллера находится в другой сборке? - PullRequest
26 голосов
/ 26 сентября 2011

Моя цель состоит в том, чтобы изменить реестр контроллеров asp.net mvc, чтобы я мог создавать контроллеры и представления в отдельной (дочерней) сборке и просто копировать файлы View и библиотеки DLL в приложение MVC хоста, и новые контроллеры эффективно«Подключен» к хост-приложению.

Очевидно, что мне понадобится какой-то шаблон IoC, но я в растерянности.

Я думал, что нужно иметь дочернюю сборку со ссылкой на system.web.mvc, а затем простоначните строить классы контроллеров, унаследованные от Controller:

Отдельная сборка:

using System.Web;
using System.Web.Mvc;

namespace ChildApp
{
    public class ChildController : Controller
    {
        ActionResult Index()
        {
            return View();
        }
    }
}

Ууу все отлично и денди.Но затем я посмотрел на изменение реестра контроллера хост-приложения для загрузки моего нового дочернего контроллера во время выполнения, и я запутался.Возможно, потому что мне нужно более глубокое понимание C #.

В любом случае, я подумал, что мне нужно создать класс CustomControllerFactory.Поэтому я начал писать класс, который переопределяет метод GetControllerInstance().Когда я печатал, intellisence выскочил это:

Host MVC Application:

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

Теперь, в этот момент я в растерянности.Я не знаю, что это делает.Первоначально я собирался написать класс «Загрузчик контроллеров», такой как локатор служб, например:

Host MVC Application:

public class ControllerLoader
{
    public static IList<IController> Load(string folder)
    {
        IList<IController> controllers = new List<IController>();

        // 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);?Или мне вообще следует использовать другой подход?

Ответы [ 4 ]

26 голосов
/ 26 сентября 2011

Ссылка на другую сборку из корневого проекта 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 }
    );

}

Обратите внимание на дополнительный аргумент namespaces для метода MapRoute.

3 голосов
/ 21 сентября 2013

Ваш другой проект должен быть настроен как область, и вы получите желаемый результат.Класс регистрации области внесет ваш проект области в смесь.Затем вы можете просто вставить dll в работающее приложение, и оно будет работать без сборки всего приложения и его повторного развертывания.

Самый простой способ сделать это - добавить новый проект mvc в ваше решение и иметь Visual Studioсоздайте новый проект внутри / area / mynewprog /.Удалите все файлы, которые вам не нужны, и добавьте класс регистрации области, чтобы подключить его.

Создайте проект, возьмите его dll и поместите в каталог bin работающих веб-сайтов, и это ..

Тогда вам просто нужно разобраться с представлениями и прочим, либо скомпилировать их в dll, либо скопировать их на сервер в папку Area / mynewproj /.

1 голос
/ 17 февраля 2016

Создайте отдельный модуль, как показано. Плагин Структура проекта:

Plugin Project structure

Обратите внимание, что некоторые файлы были исключены из проекта.

Файл 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) в текущий домен приложения.После этого asv.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");
0 голосов
/ 26 сентября 2011

Мой опыт работы с контроллерами таков, что это просто работает.Скопируйте сборку в каталог bin (или добавьте ссылку на сборку, и она будет скопирована для вас)

Я не пробовал с представлениями

...