Внешний вид платформы и одного из модулей
Наша компания долго развивала один модульный ecommerce продукт на WPF технологии, было принято решение мигрировать все это творчество на web. В итоге получились два разных продукта: один — платформа, про которую и пойдет речь в статье, а другой — само прикладное решение, реализованное с помощью набора модулей.
Используемый стек технологий
Оговорюсь, что наш выбор был обусловлен большим опытом работы с продуктами Microsoft.
Решено было использовать следующий стек технологий:
ASP.NET MVC 5.0 — в качестве web хост технологии,
ASP.NET Web API 2.0 — для реализации REST сервисов,
Entity Framework 6.0 — ORM,
EF Migrations — для изменений схемы и данных БД,
ASP.NET Identity — задачи авторизации и идентификации,
AngularJS — для SPA интерфейса. Основной причиной выбора стала его распространненость и хорошая документация, до этого опыта работы с данной технологией не было вообще. Забегая наперед, скажу, что мы ни разу не пожалели о сделанном выборе.
Архитектура
Сама платформа и модули написаны с использованием парадигм DDD, SOLID, Test Driven Development. Для презентации, конечно же, MVVM (спасибо AngularJS — переход с WPF не вызвал никаких затруднений).
Возможности платформы
Рассмотрим подробнее список основных возможностей платформы. Важно понимать, что это список возможостей именно платформы, а не прикладного функционала.
Свой Style Guide
Нами была разработана собственная тема приложения на принципах MCSS и создан свой style guide, а также визуальный конструктор элементов навигации (блейдов), позволяющий легко формировать разметку для последующего использования в модулях расширений.
Система навигации
Здесь представлена единая концепция навигации в пользовательском интерфейсе. Нам очень понравилась идея навигации нового портала portal.azure.com c горизонтальным скроллингом, поэтому решено было взять ее за основу.
Основными элементами навигации платформы являются:
- “blade” — аналог окон в классическом интерфейсе;
- “widget container” c размещающимися в них “widget”
- главное меню приложения — “main menu”
Модульность
Платформа предоставляет возможность расширения функциональности системы в режиме runtime путем установки соответсвующих модулей расширения. Учитывая, что каждый модуль может предоставлять свой пользовательский интерфейс и сервисы REST API, платформу можно использовать для гибкой найстройки под конкретную специфику.
Модульность стала одной из самых сложных задач; для ее решения нам пришлось адаптировать Microsoft PRISM из WPF и заставить работать в ASP.NET MVC.
Модули снабжены информацией о версиях и зависимостях, которая учитывается системой при инициализации и установке модулей в систему.
Помимо расширения пользовательского интерфейса и API, каждый модуль может использовать собственную схему БД с поддержкой миграции данных при изменениях версий, а также расширять или перекрывать функциональность из других модулей благодаря Unity — IoC and Dependency injection контейнеру.
Все точки расширения интерфейса перечислять не буду, упомяну лишь некоторые из них: главное меню, тулбары, виджеты, уведомления и пр.
Остальные полезности :)
- Авторизация и идентификация с возможностью федеративной идентификации — было реализовано на Microsoft ASP.NET Identity.
- Управление пользователями и правами — собственная реализация с готовым интерфейсом.
- Работа с бинарными данными (файлами) — расширяемая система предоставляет API по загрузке файлов в локальное хранилище на диске, или сетевую папку, или в azure blob storage. Может быть расширена на любую другую систему хранения.
- Фоновые задачи с планированием — реализованная с помощью бибилиотеки Hangfire, довольно гибкая и функциональная система, обладающая собственным интерфейсом по мониторингу.
- Система динамических настроек — позволяет декларировать настройки и работать с ними через стандартный интерфейс, либо из кода.
- Система динамических свойств — позволяет динамически расширять любые пользовательские объекты новыми простыми свойствами через стандартный интерефейс, либо из кода.
- Кэширование — готовый подход к кешированию с возможностью использовать различные системы для хранения кеша (AppFabric, WEB Cache и пр.)
- Система рассылки уведомлений, основанная на шаблонах — все возможности по определению уведомлений, редактированию шаблонов, уведомлениям с поддержкой локализации, планированию и логом рассылки, а также поддержка множества каналов рассылки (email, sms и пр).
- Общая система экспорта и импорта данных из модулей — единый интейрфейс и формат данных с реализацией специфики в конкретных модулях.
Это не серебрянная пуля, но все же...
В результате получилась весьма неплохая система, позволяющая при наличии достаточного опыта быстро построить административную часть web проекта средней сложности. Либо использовать в качестве копилки идей или примера, откуда можно позаимствовать кое-что для своих проектов.
Более подробную информацию о платформе можно прочитать здесь: docs.virtocommerce.com/display/vc2devguide/Working+with+Platform.
На данной платформе было построенно решение модульного ecommerce frameworkа, работающий пример которого можно посмотреть по этой ссылке: Virto Commerce online demo (frontend and admin).
Сам проект платформы находится здесь: github.com/VirtoCommerce/vc-community. Проект находится в активной стадии разработки, так что будут полезны любые ваши комментарии и пожелания.
Если будет интерес, в следующей статье я могу рассказать про ecommerce решение более детально.
Комментарии (41)
xGromMx
25.07.2015 12:06Xu4
25.07.2015 17:59+1А кто мешает в примере кода «Angular 2.0» убрать методы «updateFullname», «firstNameChanged» и «lastNameChanged», добавив метод «getFullName», который будет возвращать имя-фамилию? Кто-то, мне кажется, специально добавил мусора в пример, чтобы код на «Aurelia» выглядел лучше. В Angular можно биндить переменные напрямую к инпутам. Биндить инпут к переменной, единственное предназначение которой — хранить значение, которое передастся в метод, который обновляет другую переменную — это я и называю мусор в коде.
sitox
25.07.2015 20:15+3Выглядит 1 в 1 как portal.azure.com такие же элементы и такая же модульность.
VirtoCommerce Автор
25.07.2015 21:00это была идея, похоже на поверхности, совершенно разные внутри (angularjs vs knockout)
VirtoCommerce Автор
27.07.2015 12:20Прелесть в том, что теперь это есть не только у Microsoft, мы
отнялипозаимствовали ЭТО у них и заставили служить людям.
Полемизировать на тему angularjs vs knockout можно долго и как правило безрезультатно, я считаю, что это вообще вопрос выбора сугубо эстетический. И один и другой это всего лишь инструменты, эффективность которых напрямую зависит от прямоты рук их использующих.
OlegoO
25.07.2015 22:02+1Понятно что ноги дизайна растут от azure портала :).
Интересно было бы услышать все-таки критерии выбора angularjs vs knockout, остальные технологии у вас от MS.
Плюс как понимаю динамическая коллекция разных блоков — блейдов с разным контентом не совсем типичная задача для ангуляра. Вы что-то свое допилили или решили стандартными средствами?
Razaz
25.07.2015 22:08+41. Чем не устроила модульность типа Orchard? Там лицензия позволяет все тягать к себе.
2. Зачем было придумывать packaging когда есть Nuget.Core?
3. Откуда вы выкопали Unity?
4. Вас не смущает стартап файл на 460 строк?
5. За Resource Ownership бить ссаными тряпками. Если так приперло самому себе токены выдавать — прикрутите OpenId Connect и получайте IdToken.
6. Для этого есть Bower.
<package id="Angular.UI.Bootstrap" version="0.12.0" targetFramework="net451" /> <package id="Angular.UI.Utils" version="0.1.1" targetFramework="net451" /> <package id="angularjs" version="1.3.3" targetFramework="net451" /> <package id="angular-ui-grid" version="3.0.0" targetFramework="net451" /> <package id="Angular-UI-Router" version="0.2.8.0" targetFramework="net451" />
7. Как ваша лицензия дружит с Hangfire?VirtoCommerce Автор
26.07.2015 01:221. В Orchard это классический MVC проект с возможностью динамической компиляции модулей, у нас были немного другие требования к модульности. Тем более реализация в Orchard нам показалась чересчур сложной для переноса в наш проект.
2. Изначально использовали Nuget для упаковки и установки модулей но пришлось отказаться в виду определенных сложностей адаптации под наш модульный движок. (если интересно я смогу позже написать список проблем с которыми мы столкнулись при работе с nuget.core)
3. Выбор Unity обусловлен опытом работы с этой библиотекой. А какие альтернативы? AutoFac, Castle Wizdor? на мой взгляд это равнозначные продукты.
4. Да это мы исправим, там еще есть что делать :) (краснею)
5. Тут не совсем понятно что вы имеете в виду.
6. Ждали до последнего когда выйдет 2015 студия там обещали поддержку Bower, как выйдет сразу же переведем на нормальный сборщик.
7. Hangfire используется в качестве расширенияRazaz
26.07.2015 13:331. Я просто не вижу сильной разницы с вашим проектом. Тот же MVC, WebApi, свои ресурсы у каждого модуля. Вы сожете обрезать модульность орчарда что бы не заморачиваться с компиляцией вьюх и тд.
2. Единственное что там могло напрягать — кастомизация манифестов. Но это решаемо.
3. Autofac или StructureMap. К Unity после них вообще не хочется прикасаться. И не понятно когда они докрутят поддержку DNX.
5. Если выхотите отдавать токены в свой UI, то поставьте вот это — IdentityServer3.
Там и нормальная страница логина со всеми свистелками в виде CSP и тд, и полностью валидная реализация OpenId Connect. Вы хотя бы на свою страничку накиньте X-Frame-Options и добавьте csrf хотяб.
6. Ими можно и сейчас пользоваться. Плюс посмотрите на минификацию. Сейчас даже не сосчитать сколько js файлов загрузилось.VirtoCommerce Автор
27.07.2015 21:321. Orchard основан на NuGet, который добавляет слишком много сложности в разработке модуля
2. еще раз, зачем усложнять простые вещи
5. IndentityServer оказывается сложным и требует дополнительных шагов не нужны для большинства пользователей
6. Вы можете включить в ASP.NET script bundle и количество scriptov будет снижена до всего лишь несколькиRazaz
28.07.2015 00:491. Какие? Все кто хоть раз делал модули прекрасно смогут все сделать. Очень удобно иметь сервер с модулями в кластере. Плюс у вас есть базовая дока, референс сервера галереи и тулзов для работы с пакетами.
2. Дак это как раз просто — вы берете готовый компонент и используете его, и все участники Opensource community знакомые с ним сразу понимают что к чему.
5. Что там сложного? Это простой Middlware который просто решает тонну задачь за вас, не совершая при этом ошибок типа отсутствия CSP и X-Frame-Options? Причем из коробки есть интеграция с Asp.Net Identity и вся необходимая информация для его внедрения.
6. А почему на демке не включено?VirtoCommerce Автор
28.07.2015 01:161. Nuget modules слишком сложные и ориентированы на .net разработчика, мы хотели чтобы другие разработчики имели возможность писать расширения, например JavaScript только расширения.
5. Сложность в настройке и установке, например установкой в azure или Web PI, мы собираемся добавить больше расширяемости и поддержку IdentityServer, но в качестве расширения.
6. Автоматическое развертывание не был настроен правильно
изменилось
<compilation debug="true" targetFramework="4.5.1" /> на <compilation debug="false" targetFramework="4.5.1" />
теперь работаетRazaz
28.07.2015 11:00+11. Вы сами ставите nuget модули с js скриптами… Что там сложного?
5. Это Owin Middleware. Его не надо ставить отдельно.
lair
26.07.2015 12:13За Resource Ownership бить ссаными тряпками. Если так приперло самому себе токены выдавать — прикрутите OpenId Connect и получайте IdToken.
А вы не развернете свою мысль, чтобы и людям, которые меньше в теме, стало понятно, почему нельзя так делать?Razaz
26.07.2015 13:21Resource Ownership подразумевает прямую передачу секретов пользователя по сети. В основмном используется только для обратной совместимости. Для всего остального есть OpenId Connect. Если это js клиент то можно использовать Implicit Flow, а если приложение — то просто открыть страничку и ждать редиректа на oob://. Пример можно подглядеть в клиенте Origin(хоть что-то в нем они сделали хорошо)
lair
26.07.2015 16:10Окей, а если вместо resource ownership использова OAuth 2 Implicit или OAuth 2 Authorization Code?
Razaz
26.07.2015 18:52Я выше и отметил. Но лучше уже всетаки OpenId Connect. В целом сам подход не очень красивый для приложения, которое позиционируется фреймворком. Меняем Middleware — и все отваливается. Хотим 2FA — все отваливается. ИМХО страница логина должна быть как минимум изолированна от основного приложения. А еще плюс кейсы блокировки, восстановления пароля, федеративной аутентфикации и тд.
lair
26.07.2015 18:53Я просто (для себя, на самом деле) пытаюсь понять — когда надо использовать OAuth 2, а когда OpenId Connect.
Razaz
26.07.2015 22:14OpenId Connect это стандартизированный слой получения информации о пользователе поверх OAuth2 плюс он подразумевает такой процесс как аутентификация, который в OAuth2 не упоминается(протокол авторизации). Например можно указать какой тип страницы логина показать — полную или для wap устройств. Так же стандартизирует клэймы. Если у вас сайт — можно начать с Authorization Code и дальше смотреть по удобству. Если приложение — то Implicit, хотя лучшие собаководы(даже Гугл) рекомендуют всегда использовать первый вариант. Показываете контрол браузера и ждете редиректа на oob://(out of box). Нет смысла использовать один вместо другого, так как они дополняют друг друга. Если есть вопросы — могу ответить в личку.
NewOrdered
27.07.2015 12:10YP-T9 отличный плеер кстати. У меня с 2007 года работает до сих пор.
VirtoCommerce Автор
27.07.2015 12:32Да, каталог намерено наполнен устаревшими моделями. Первоначально была идея использовать для тестового каталога проигрыватели пластинок, но пришлось отказаться в виду незначительного ассортимента на рынке.
Krio
27.07.2015 13:48Работа проведена конечно большая, только функционал ui-router'а практически не используется.
А сборщик скриптов аж просится в проект.VirtoCommerce Автор
27.07.2015 16:21Вы верно заметили, ui-router используется только для домашнего state модуля и не используется для навигации внутри него, именно поэтому при навигации внутри модуля не изменяется navigation bar. Это ограничения связанно с горизонтальной системой навигации, просто ну ни как не могли вписать это в концепцию ui-route.
А сборщик скриптов конечно же добавим. Просто изначально для сборки скриптов используем ASP.NET Bundle, но потом как показала жизнь нужно еще и как то работать с зависимостями и пр так что будем наверно искать компромиссный вариант, что-то вроде ASP.NET Boundle + Bower или Grunt. Будем рады любой помощи по этому направлению.Razaz
27.07.2015 17:01Bower+Gulp наше все) Проблема толкьо в том, что вам это надо как-то делать при старте приложения, так как модули не детерменированы. Как вариант посмотреть еще в сторону Cassette-подобного подхода.
Sergiy
А с выходом Angular2 что будете делать?
VirtoCommerce Автор
без проблем, будем мигрировать в 2.0
xGromMx
С выходом Angular 2 я уйду на Aurelia, Vue, Virtual DOM, или на React(хотя частично уже на нем). Потому что синтаксис Angular 2 ужасен.
kvaki
Не знаю чем вам так не понравился Angular, но помоему Virtual DOM хуже как и Aurelia во много раз. Aurelia хоть и прост в написании, но не такой маштабный и без большой поддержки Google.
xGromMx
Роб не просто так ушел из их команды
xGromMx
Первый ангуляр мне больше по душе.
kvaki
Помоему второй еще не вышел, а ты его уже поливаешь…
xGromMx
я не поливаю, просто есть ряд вещей, что выглядят не очень.
kvaki
Ну просто многие так же как и ты не любили HTML5 до его выхода. Большая часть юзеров кричала: Да зачем он нужен, какая то лобуда итп итд. Как только HTML5 вышел месяц-два криков. А потом как то начали притягиваться, потому что HTML5 более удобен, да и браузеры уже все перешли. Это как рисовать в фотошопе линии, или использовать CSS3 для этого. В общем то или использовать форд 1998 года, или же порше 2009, на что падет выбор если цена одинаковая?
monolithed
Отличия не такие и большие
Тот же Cayenne в 958-м кузове, далеко не каждый сможет содержать, поскольку за страховку вам придется отдать не меньше 210, двойной налог не меньше 100, за обслуживание и содержание не меньше 100 и за бензин не меньше 150, диски, резина (300 / 3 года = 100), мойка раз в три дня, а то и чаще (365 / 3 * 1000 = ~121) и прочее.
Для вас наверное выбор очевиден, но по личному опыту, это далеко не так.
VirtoCommerce Автор
я думаю, что много будет меняться до angular2 выпуска
xGromMx
я слежу за их развитием, то, что они применили reactive pattern у себя — это не плохо.