наследование сайтов ASP.NET MVC из общего приложения-шаблона? (мульти аренды)

Мы создаем около 10 сайтов ASP.NET MVC с общим набором функций (и соответствующими URL-адресами, маршрутами, контроллерами, действиями и представлениями). Все сайты также будут иметь общий базовый набор объектов домена (например, пользователей, компаний) и базовых атрибутов этих объектов (например, имя, адрес и т. д.).

Но каждый сайт также будет сильно настраиваться и расширяться по сравнению с базовым. Например, наш сайт для крупных публичных компаний будет иметь поля «Дочерняя компания» и «Символ акции» в объекте домена «Компания», а наш сайт для стартапов будет иметь атрибуты «Венчурная фирма» и «Финансирование». Внешний вид также будет значительно различаться, хотя мы пытаемся сохранить HTML как можно более согласованным (по модулю дополнительных полей формы для дополнительных атрибутов объекта домена и т. д.). Мы также будем экономно переопределять изображения, чтобы мы могли, например, повторно использовать одну и ту же графику кнопок на разных сайтах.

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

Я знаком с тем, как работать с несколькими арендаторами с ограниченной настройкой, как вы найдете в StackOverflow/SuperUser/ServerFault (или MSDN/TechNet, если на то пошло), где пользовательский интерфейс немного отличается, а модель данных более или менее идентичный. Но когда модели и пользовательский интерфейс очень разные (но наследуются от общей базы), я менее уверен, как действовать дальше.

Меня меньше беспокоят операционные проблемы, поскольку мы, вероятно, будем запускать каждый сайт в отдельном домене приложений и размещать их в отдельных базах данных. Меня больше беспокоит снижение долгосрочных затрат на обслуживание кода, повышение гибкости (например, простота добавления новых функций в базу без нарушения производных приложений) и реализация краткосрочной экономии затрат на разработку/тестирование по мере создания нашего второго, 3-й, 4-й и т.д. сайт.

Я ищу как общие рекомендации и предложения, так и конкретные предложения о том, как сделать эти рекомендации реальными, используя современные методы ASP.NET MVC.

Я понимаю, что это очень общий вопрос, но для начала я ищу как руководство высокого уровня, так и конкретные советы и рекомендации о том, как применять это руководство с ASP.NET MVC, включая такие вещи, как:

  • рекомендации по разделению базового/производного между проектами Visual Studio
  • советы по управлению исходным кодом, чтобы избежать разветвления
  • советы по схеме базы данных (FWIW, все наши базы данных небольшие - менее 10 000 строк на таблицу, поэтому стоимость разработки / тестирования является большей проблемой, чем производительность БД)
  • советы по повторному использованию контроллеров/представлений/и т. д. соответствующие «базовым» атрибутам модели, особенно повторное использование пользовательского интерфейса для таких вещей, как формы «новых клиентов», которые будут иметь сочетание базовых и производных атрибутов.

У кого-нибудь есть хороший совет, как создать такое многопользовательское приложение?


person Justin Grant    schedule 30.09.2009    source источник


Ответы (4)


Вот что мы делаем, и в настоящее время это работает довольно хорошо примерно на 8 сайтах.

  • Определите основной проект MVC для ваших контроллеров, ViewModels, HttpApplication, маршрутов и т. д. Это скомпилирует в DLL и скомпрометирует большую часть вашего сайта.

  • Создайте базовый набор представлений по умолчанию, сценариев, изображений и т. д. для вашего сайта. Они будут использоваться по умолчанию для ваших отдельных сайтов.

  • Для каждого клиента создайте любые настраиваемые контроллеры, маршруты и т. д., которые вам понадобятся в проекте, который компилируется в другую dll.

  • Также для каждого клиента воссоздайте любые представления, сценарии, изображения, которые вы хотите использовать.

Чтобы вышеуказанные шаги работали вместе, вам нужно написать немного клея. Первая часть клея — это пользовательский движок просмотра. Вы захотите настроить стандартный механизм представления, чтобы сначала искать представления в папке, специфичной для вашего клиента, а затем в папке по умолчанию. Это позволяет легко переопределить макет по умолчанию для каждого клиента.

Второй способ заставить все работать — заставить ваше основное приложение загружать маршруты, контроллеры и т. д. из конкретной сборки вашего клиента. Для этого я использую Managed Extensibility Framework (MEF) для предоставления одного метода Register. Вызов этого метода в моем коде сборки клиента регистрирует маршруты и любые другие потребности клиента.

Вот общий вид того, как выглядит структура папок моего сайта, при этом SiteContent сначала проверяется на просмотры:

  - AppContent
  - AppContent/Static
  - AppContent/Static/Images
  - AppContent/Static/Scripts
  - AppContent/Static/Styles
  - AppContent/Views
  - AppContent/Views/Shared

  - SiteContent
  - SiteContent/Static
  - SiteContent/Static/Images
  - SiteContent/Static/Scripts
  - SiteContent/Static/Styles
  - SiteContent/Views
  - SiteContent/Views/Shared

  - web.config
  - Global.asax

У меня есть помощники, которые я могу использовать, такие как SiteImage и AppImage, для использования в моих представлениях. Кроме того, я заставляю каждый из своих клиентских сайтов использовать определенные имена для своих главных страниц, которые я никогда не определяю в своих значениях по умолчанию для AppContent.

Я понимаю, что это грубый обзор, но сейчас он работает достаточно хорошо для нас.

person Brian Vallelunga    schedule 10.05.2010
comment
Я надеюсь, что вы можете ответить на это. Как делаешь маршруты? Я получаю сообщение об ошибке, когда маршрут находит несколько экземпляров контроллера (один в проекте AppContent и один в проекте SiteContent). - person Chris; 20.12.2014

В настоящее время я участвую в подобном «наборе» проектов, которые сосредоточены на том, чтобы позволить клиентам подавать заявки на продукты в Интернете, но у меня очень похожие требования к тому, какую информацию собирать, где единственные различия касаются конкретных частей информации о продукте или немного различные законодательные требования.

Одна вещь, которую мы попытались сделать, это создать страницы (комбинации моделей, представлений и контроллеров), которые можно повторно использовать сами по себе, поэтому любое приложение может использовать страницу для сбора информации, но перенаправлять на следующую страницу, которая может отличаться в зависимости от типа продукт подается на. Для этого мы используем абстрактные базовые контроллеры в форме шаблона метода шаблона, которые содержат в основном всю необходимую логику контроллера (включая методы действий с применяемыми фильтрами действий), но затем используем абстрактные методы для выполнения определенных действий, таких как перенаправление на следующая страница в процессе. Это означает, что конкретная реализация контроллера, используемого конкретными потоками страниц приложения, может содержать только один метод, возвращающий RedirectToActionResult, соответствующий следующей странице в потоке. Существует также довольно много других вещей, которые управляют движением назад и такими навигационными вещами, но с помощью фильтров действий вы можете настроить их так, чтобы вам не приходилось беспокоиться об этом, как только вы настроите его и начнете работать. .

Существуют также объекты базовой модели, которые содержат общие функции, будь то логика проверки или логика сохранения состояния.

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

Следствием этого является то, что у нас есть структура проекта, состоящая из базовой dll, которая содержит абстрактные классы верхнего уровня, интерфейсы и служебные классы, а также помощники html, фильтры действий и т. д. Затем у нас есть проекты mvc, которые содержат конкретные реализации базовые контроллеры, модели и т. д., а также представления и мастер-страницы.

Самое сложное — делиться взглядами, и я не думаю, что мы еще должным образом разобрались с этим. Хотя с MVC 2.0, содержащим области, я думаю, что это станет меньшей проблемой, но я еще не поиграл с этим. (см. сообщение Скотта Гу о версии 2.0: http://weblogs.asp.net/scottgu/archive/2009/07/31/asp-net-mvc-v2-preview-1-released.aspx) Одна вещь У меня есть POCed, который выглядит так, как будто он будет работать, используя базовый проект MVC для содержания общих представлений, а затем расширяя механизм представления по умолчанию для поиска этого проекта на веб-сервере при поиске представления для рендеринга (что довольно легко сделать). Области, хотя это гораздо более приятное решение.

Что касается системы управления исходным кодом, мы используем svn, и я думаю, что вы разумно беспокоитесь о ветках. Это не то, с чем нам еще приходилось иметь дело, но мы, вероятно, собираемся использовать git, так как кажется, что он делает процесс ветвления и слияния намного менее болезненным.

Не уверен, что это вам сильно поможет, но я определенно рекомендую иметь в виду абстрактные контроллеры и модели, а также посмотреть, как вы можете использовать html-помощники и частичные представления для группировки схожих частей функциональности.

person Dean Johnston    schedule 30.09.2009
comment
Спасибо Дина за развернутый ответ! Я собираюсь изучить ваши предложения и, возможно, создать несколько прототипов для исследования. - person Justin Grant; 05.10.2009

Майк Хэдлоу подробно описывает, как это сделать:

http://mikehadlow.blogspot.com/2008/11/multi-tenancy-part-1-strategy.html

person Chris Missal    schedule 30.09.2009
comment
Я не впечатлен... Он хорошо говорит, но все это пустые дискуссии без конкретики, и в его проекте с открытым исходным кодом вообще нет упоминания о стратегии мультиарендности; похоже, у него не было времени, чтобы реализовать это. - person Robert Harvey; 30.09.2009

Один из способов сделать это — использовать ветвление в системе управления версиями.

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

person Shiraz Bhaiji    schedule 30.10.2009
comment
забавно, так я делал до сих пор (на основе прототипа), но изначально я предполагал, что этот подход будет хакерским и хрупким по сравнению с более традиционными подходами к разработке программного обеспечения, такими как interitance. Реализовали ли вы настройку с помощью системы управления версиями в проектах значительной сложности? - person Justin Grant; 31.10.2009
comment
Да, я знаю одну компанию, которая занимается этим. У них есть версии проекта и клиентские настройки каждой версии. Они также создали систему для отслеживания того, какая система установлена ​​у каждого клиента, и какие сценарии обновления необходимо запускать между версиями. - person Shiraz Bhaiji; 31.10.2009