Прикручиваем Umbraco CMS, как источник данных

в 7:44, , рубрики: ASP, cms, umbraco, метки: ,

Прикручиваем Umbraco CMS, как источник данных

Целевая аудитория: системы, которым нужна несложная CMS, не влияющая на архитектурное решение. (CMS, как хранилище контента, без генерации форм и т.п.)

Цель данной статьи – в «2х словах» показать, как можно использовать Umbraco CMS в качестве источника данных, от которого глобально не зависит основное приложение (ведь источник в любой момент можно заменить на любой другой), другими словами, как вынести CMS в отдельный проект.

Некоторое время назад я узнал об Umbraco CMS, которая сразу привлекла мое внимание. Одним из основных ее преимуществ для меня явилось ее free openSource, со всеми вытекающими. Достаточно простой и эффективный дизайн, несложный бэкграунд, большое комьюнити и широкий ассортимент бесплатных расширений. С полным списком преимуществ и недостатков можно ознакомиться в сети. Меня огорчили всего два момента:

  1. СMS предъявляет определенные претензии к структуре и платформе основного приложения, роутингу и т.п. Программирование на C# сводится к написанию User-контролов.
  2. Исходя из первого пункта, на данный момент последнюю версию (4.10) невозможно использовать с ASP.NET MVC, который я так люблю. (видел в сети вариант с проектом «смешанного типа» — ASP.NET + ASP.NET MVC, но мне он тоже не понравился)

Мне же хотелось использовать CMS исключительно как модуль администрирования контента, данные которого я мог бы получить просто подключив пару-тройку библиотек к любому другому проекту. И, насколько я понял, Umbraco не предоставляет такой возможности по умлочанию. Кроме того, мне хотелось бы самостоятельно писать разметку страниц, логику биндинга данных на C#, определять layout, не возится с xslt, на котором построен ui-engine umbraco. Проведя некоторое время в поисках и не найдя ничего подходящего пришлось решить эту задачу самостоятельно.

Стоит отметить справедливости ради, что в результате некоторые функции CMS будут недоступны в силу того, что основное приложение в него не интегрировано. Например: создание и редактирование страниц, администрирование тем, скриптов, макросов. Во всяком случае, по умолчанию. Так что, если вам нужна полнофункциональная CMS, в которой клиент должен иметь возможность выполнять все эти действия, то этот вариант не слишком подходит.

Схематически это выглядит так:
Прикручиваем Umbraco CMS, как источник данных

Итак, для начала необходимо выполнить следующее:

  • Создать проект с CMS, сконфигурировать и несколько расширить его функциональность.
  • Добавить необходимые сборки в Web-проект, сконфигурировать и написать пару строк кода.

  1. Создание проекта CMS
    • Поскольку umbraco написан на ASP.NET, в VisualStudio создаем пустой проект соответствующего типа (удаляем из него все файлы и папки)
    • Устанавливаем в этот проект «Umbraco Cms» из NuGet.
    • Запускаем проект – откроется стартовая страница конфигурирования Umbraco, где мы привязываем его к базе данных.

  2. Расширение Umbraco
    Background:
    При использовании cms в отдельном проекте есть один существенный нюанс, который требует некоторых дополнительных телодвижений, а именно: поскольку в web-приложении уже невозможно сделать что-то вроде umbraco.GetCurrentItem (), т.к. его контекст к cms никак не привязан, нужно каким-то образом получать необходимые нам узлы.
    Umbraco.API дает возможность делать это по нескольким параметрам узла, ни один из которых до конца не гарантирует, что мы получим именно тот самый узел, либо получим что-то вообще.

    Казалось бы, получение узла по его ID является идеальным решением — можно захардкодить необходимые ID и спокойно делать uQuery.GetNode(int nodeId), но в umbraco реализована сквозная нумерация узлов, и, насколько я понял, не реализован их мержинг в случае установки пакета с теми же узлами. По-этому, чтобы минимизировать работу, связанную с поиском нужных узлов в будущем, реализован следующий механизм:

    Прикручиваем Umbraco CMS, как источник данных

    На рисунке реализация кастомного контрола для Umbraco. Контрол отвечает за задание ассоциаций между узлами cms и кастомным енумом из web-приложения (DropDown мапится на enum, узел выбираем через ContentPicker). Это простейшая реализация концепции, т.е. вместо енума список названий узлов может иметь любую структуру и храниться не только в енуме. К примеру, если в приложении нужно знать о 100 узлах, а не о 10ти – можно придумать что-то по-сложнее. Кстати, таким образом можно реализовать и локализацию web-сайта, добавив наборы ассоциаций для разных культур (стрелка Ru-Ru). Перед сохранением данных из ContentPicker’а получаем реальный ID узла.

    Также при большом желании здесь можно проверять, не пропали ли узлы из umbraco, ожидаемые в web-приложении, вывести предупреждения, писать мэйлы и т.п., предвосхищая появление NotFound-ошибок.

    Данные ассоциаций сохраняем в БД Umbraco (к примеру). В простейшем случае таблица имеет следующую структуру:

    Прикручиваем Umbraco CMS, как источник данных

  3. Настройка Web-проекта
    Теперь что касается основного проекта-потребителя. Для того, чтобы получить данные, сохраненные через cms через api Umbraco, необходимо выполнить следующее:

    • Скопировать configumbracoSettings.config из корня cms в корень web-проекта
    • Установить значение свойства «XmlContentCheckForDiskChanges» в этом конфиге в true (пункт необязательный, но даст возможность мгновенного «подхватывания» изменений в cms)
    • Скопировать ключи из web.config cms в web.config проекта:
      • «umbracoDbDSN» — путь к базе cms
      • «umbracoContentXML» — путь к xml-файлу, в который cms кэширует данные. Точнее: этот файл по умолчанию находится в «App_Dataumbraco.config». Тут есть нюанс. Если cms физически размещен на другом сервере, то решение задачи требует дополнительных действий. Я не слишком глубоко вник в механизм кэширования umbraco, но думаю, что при необходимости от кэширования в файл можно и вовсе отказаться.
      • Добавить референсы на следующие сборки:
        • businesslogic.dll
        • cms.dll
        • controls.dll
        • interfaces.dll
        • umbraco.dll
        • umbraco.DataLayer.dll

    4. Доступ к данным
    Если я ничего не упустил, этого достаточно, чтобы api umbraco работали, как надо. Чтобы получить нужный узел, нужно знать его Id. Всё, что нужно сделать, это получить нужный Id из таблицы ассоциаций ItemsIdMap по имени элемента енума и культуры, если таковая имеется. Например:

    ItemsIdMap itemAssociation =  context.ItemsIdMaps.SingleOrDefault(p => p.ItemCID == CmsItemCID.News.ToString() && p.Lang == "Ru");
    
    Node node = uQuery.GetNode(itemAssociation.ItemId);
    string content = node.GetProperty(propertyName).Value;
    
  4. Вот в принципе и всё. Пример этот концептуальный, в процессе возникают различные нюансы, но это уже другая история — всё решается по мере поступления. Также отмечу, что сам еще не тестировал это решение ни на предмет всех возможностей, ни на предмет перформанса. Кстати, в данном случае удобно скачать исходники Umbraco, временно подключить вместо сборок и дебажить, если возникают непонятные проблемы, т.к. применение cms нетипично. В любом случае, пока мне это решение нравится значительно больше, чем писать админку собственными руками.
    Спасибо за внимание!

Автор: YSO

Источник

  1. An:

    Еще много статей о разработке сайтов на Umbraco + форум русскоязычной поддержки на http://www.unicodsgn.com/ru/umbdoc/

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js