2016-06-06 3 views
8

В настоящее время я работаю над проектом MVC, и я пытаюсь выяснить, как я могу расширить маршруты существующего Контроллера в пределах Района, в частности из другого проекта.Переопределение/расширение 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 в каталог bin основного проекта MVC, но это, похоже, не работает должным образом.
  • Я пробовал различные подходы к наследованию, надеясь, что новый класс будет поднят, но они не сработали (получена ошибка декларации дублирующего контроллера).
  • Я читал о попытке использовать пользовательский 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) 
    } 
); 

Update

Я попытался подход 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 в основной проект при его создании (так будет доступно) из нового пользовательского проекта.

Это, похоже, не имеет никакого значения. Я попытался перейти к URL-адресу Foo/Bar, но он просто бросил 404, как будто он его вообще не видел. Файл CustomFooController.cs находится в собственном отдельном проекте и представляет собой файл класса, а не проект MVC. Это верно? Нужно ли устанавливать правила маршрутизации в основном проекте?

+0

Что случилось с использованием наследования? В проекте-B включить ссылку на проект-main, затем контроллер-B наследуется от main-контроллера. В качестве альтернативы, используйте общий класс в качестве базы и соответствующим образом настройте свои маршруты. –

+0

Итак, я должен наследовать свой контроллер Project B от 'FooController' в проекте A? Если да, то как это повлияет на мою маршрутизацию, поскольку я хочу иметь возможность использовать ту же базовую маршрутизацию, то есть «Foo/ProjectAAction» или «Foo/ProjectBAction». Будет ли это работать? –

+0

Все маршруты к контроллеру-B также будут получать основные действия контроллера, поскольку они являются частью контроллера-B по наследованию. т.е. ваши маршруты не будут знать о главных контроллерах проекта. –

ответ

6

Контроллер Наследование

Использование наследования как Chris упоминалось в разделе комментариев, вероятно, будет лучшим способом идти об этом, а также. Это особенно актуально, если вы уже вытекающие из другого базового класса контроллера, как ApplicationController в вашем примере:

// ProjectA is assumed to be your "main" MVC application 
public class CustomFooController : ProjectA.Controllers.FooController 
{ 
    [Route("Foo/Bar")] 
    public ActionResult Bar() 
    { 
     return Content("Bar"); 
    } 
} 

Атрибут маршрутизации здесь чрезвычайно важен, так как вы не хотите, чтобы ваши существующие маршруты, чтобы запутать два контроллера или упускать из вида их.

регистрирующие атрибутов Маршруты

Поскольку вы используете атрибут маршрутизации с помощью атрибута [Route] в вашем разделе ProjectB, вы хотите, чтобы убедиться, что вы явно установить его в RouteConfig.cs вашего проекта Projecta так, что он может правильно идентифицировать его с помощью метода Routes.MapMvcAttributeRoutes(), как показано ниже:

public static void RegisterRoutes(RouteCollection routes) 
{ 
    // This is important to set up your Route Attributes 
    routes.MapMvcAttributeRoutes(); 

    // Route declarations omitted for brevity 
} 

Аналогично, если вы используете районы, вы хотите, чтобы настроить это в пределах соответствующего AreaRegistration.cs файла в качестве хорошо:

public override void RegisterArea(AreaRegistrationContext context) 
{ 
    // Wire up any attribute based routing 
    context.Routes.MapMvcAttributeRoutes(); 

    // Area routing omitted for brevity 
} 

Scoping Маршруты

Наконец, последнее, что вы хотите, чтобы убедиться, что нужно сделать, это правильно «Scope» ваши маршруты, чтобы расставить приоритеты основное пространство имен в пределах RouteConfig.cs вашего основного Projecta применение:

public static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 
    routes.MapMvcAttributeRoutes(); 
    routes.MapRoute(
     name: "Default", 
     url: "{controller}/{action}/{id}", 
     defaults: new { controller = "Foo", action = "Index", id = UrlParameter.Optional }, 
     // This will prioritize your existing Controllers so they work as expected 
     namespaces: new[] { "ProjectA.Controllers"} 
    ); 
} 

Попадая Ссылки Across

Вы упомянули использование события сборки, чтобы скопировать DLL из проекта ProjectB в ваш основной проект ProjectA, и в этом случае должно быть хорошо. Вы в основном должны некоторые способ доступа к нему и просто xcopy вроде следующего должно быть хорошо в большинстве сценариев:

xcopy /E /Y /S "$(ProjectName).dll" "$(SolutionDir)\ProjectA\Bin\" 

Собираем все вместе

Если вы подключены до всех этих шаги правильно, вы должны иметь возможность очистить/перестроить существующее решение.После этого, дважды проверьте, чтобы убедиться, что у вас есть соответствующий DLL в вашем ProjectA bin каталоге:

enter image description here

Если это есть, то вы на правильном пути, и должны быть в состоянии запустить ваш главный приложение и перейдите к ~/Foo увидеть следующее:

enter image description here

Аналогично, навигации по ~/Foo/Bar должен подобрать соответствующий маршрут атрибут, который был определен в вашем другом контроллере и служат надлежащее содержание:

enter image description here

+0

Большое вам спасибо! Это работало так, как я себе представлял. Спасибо за понимание того, что я пытался сделать! –