В последнее время я сосредоточился на создании приложения ASP.NET MVC, которое может размещать сторонние плагины MVC. В идеале разработка этих плагинов будет следовать этим правилам:
- Плагины могут быть разработаны в стандартном проекте MVC и иметь возможность использовать всю существующую инфраструктуру инфраструктуры ASP.NET MVC.
- Сложность компиляции проекта MVC плагина и включение в приложение MVC хоста не должно быть серьезным.
- Любые изменения в нормальном потоке разработки приложения MVC будут минимальным значением
После некоторых исследований я придумал следующие подходы для достижения этого, каждый из которых имеет свои преимущества и недостатки.
Подход 1 - сборка MVC-плагина, загружаемая в основной MVC AppDomain
Рабочий поток
- Разработка плагина внутри отдельного проекта MVC.
- Скомпилируйте сборку и загрузите ее и любые зависимости в приложение-хост через
PreApplicationStartMethodAttribute
, MEF или базовую ссылку на сборку в проекте хоста (если это возможно). - Сопоставьте маршрут с контроллерами плагинов, чтобы плагин рассматривался как
Area
внутри хоста. - Поместите плагины в нужную папку области. Файл макета нужно будет изменить так, чтобы путь макета указывал на местоположение на основе области, а не на корень приложения (что было бы в случае проекта MVC разработки).
- Когда запрос подключается к плагину, ASP.NET будет использовать функциональность существующих областей для маршрутизации запроса на правильные контроллеры и посмотреть в нужном месте для файлов вида.
<сильные > Преимущества
- Будет работать так же легко, как если бы контроллеры были встроены в сборку хоста MVC.
- Простое включение сборок в домен приложения хоста до запуска приложения (
PreApplicationStartMethodAttribute
, ссылка на проект) и после запуска приложения ( MEF)
Недостатки
- Нет песочницы - контроллеры будут иметь тот же уровень доверия, что и хост.
Заключение
Это самый простой подход, однако он также наименее безопасен. Это существенно устраняет возможность предоставления не доверенным разработчикам создавать плагины, потому что те плагины будут иметь тот же уровень доверия, что и хост-приложение (это означает, что если хост-приложение может выполнять такие методы, как System.IO.File.Delete
, так что может быть плагин)
Подход 2 - сборка MVC, работающая в собственном AppDomain через MAF
Этот подход предполагает создание плагинов MVC, которые могут быть изолированы в свои собственные AppDomains
и использованы хостом через библиотеки System.Addin
.
Структура
-
В хосте устанавливается маршрут, который определяет, будет ли обработанный URL нацелен на плагин. Может иметь шаблон, например
example.com/p/{plugin}/{controller}/{action}/{id}
-
Все маршруты, имеющие вышеуказанный шаблон, сопоставляются с контроллером хоста, который имеет действие маршрутизации модуля. Это действие просматривает любой заданный маршрут и определяет соответствующий плагин для обработки запроса на основе сегмента
{plugin}
. -
Плагин представляет собой объект получателя/отправителя, который действует как шлюз для контроллеров плагинов. Он имеет метод AcceptRequest, который получает
RequestContext
от хоста и возвращаетActionResult
. -
Консоль плагина содержит адаптеры, которые могут сериализоваться
RequestContext
иActionResult
для передачи по границе изоляции конвейера.
Выполнение потока
-
Согласован маршрут для плагина и вызывается контроллер маршрутизации плагинов.
-
Контроллер загружает требуемый плагин в свой собственный
AppDomain
и вызывает AcceptRequest, проходя черезRequestContext
(который сериализуется по конвейеру) -
AcceptRequest получает контекст и определяет соответствующий контроллер для выполнения на основе этого запроса (используя пользовательский контроллер factory).
-
Как только контроллер завершит выполнение запроса, он возвращает объект
ActionResult
к объекту получателя, который затем передал этотActionResult
(также сериализованный по конвейеру) обратно на хостAppDomain
. -
Контроллер, который изначально назывался AcceptRequest, может затем вернуть
ActionResult
в конвейер выполнения MVC хоста, как если бы он обработал сам запрос. После этого плагинAppDomain
может быть выгружен.
<сильные > Преимущества
Плагин будет изолирован в нем AppDomain
, поэтому можно использовать любой набор разрешений, который подходит для хоста.
Недостатки
- Должна быть возможность сериализации
RequestContext
иActionResult
. - Возможно, будут разбиты другие функции ASP.NET MVC в изолированном
AppDomain
.
Заключение
Этот подход звучит неплохо на бумаге, но я не уверен, возможно ли/возможно сериализовать объекты RequestContext
и ActionResult
, а также изолировать MVC-контроллер.
Вопросы
Первый подход хорош, если код создается доверенными разработчиками. Я знаю, что я не буду удалять все файлы представления хоста или файл web.config. Но в конечном счете, если вы хотите, чтобы сторонние разработчики создавали плагины для вашего приложения MVC, вы должны иметь возможность изолировать свой код.
Из всех моих исследований библиотека System.Addin
упрощает реализацию среды хоста/плагина при использовании простых библиотек классов на основе API. Однако кажется, что это непросто сделать, когда задействован MVC.
Некоторые вопросы у меня есть:
- Возможно ли, что второй подход, который я изложил здесь, выполним?
- Есть ли лучший способ сделать это?
- Будут ли более простые способы обеспечения изоляции плагина MVC в будущем?