Подтвердить что ты не робот

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

Моя цель - изменить регистр контроллера 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();
        }
    }
}

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

Во всяком случае, мне показалось, что мне нужно создать класс 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;
    }
}

И затем я планировал использовать список контроллеров для регистрации их в контроллере factory. Но как? Я чувствую, что нахожусь на грани выяснения этого. Я думаю, все это сводится к этому вопросу: как мне подключиться к return base.GetControllerInstance(requestContext, controllerType);? Или, должен ли я использовать другой подход вообще?

4b9b3361

Ответ 1

Ссылка на другую сборку из проекта "root" 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.

Ответ 2

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

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

Создайте проект, возьмите его dll и поместите в свой текущий каталог bin bin и его..

Вам просто нужно иметь дело с представлениями и т.д., либо скомпилировать их в dll, либо скопировать их на сервер в области/mynewproj/folder.

Ответ 3

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

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

Ответ 4

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

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

Файл 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");