Прикручуємо umbraco cms, як джерело даних, savepearlharbor

Цільова аудиторія. системи, яким потрібна нескладна 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, як джерело даних, savepearlharbor

Отже, для початку необхідно виконати наступне:
  • Створити проект з CMS, конфігурувати і дещо розширити його функціональність.
  • Додати необхідні збірки в Web-проект, конфігурувати і написати пару рядків коду.
  1. Створення проекту CMS
    • Оскільки umbraco написаний на ASP.NET, в VisualStudio створюємо порожній проект відповідного типу (видаляємо з нього всі файли і папки)
    • Встановлюємо в цей проект «Umbraco Cms» з NuGet.
    • Запускаємо проект - відкриється стартова сторінка конфігурації Umbraco, де ми прив'язуємо його до бази даних.
  • розширення Umbraco
    Background:
    При використанні cms в окремому проекті є один істотний нюанс, який вимагає деяких додаткових рухів тіла, а саме: оскільки в web-додатку вже неможливо зробити щось на зразок umbraco.GetCurrentItem (), тому що його контекст до cms ніяк не прив'язаний, потрібно якимось чином отримувати необхідні нам вузли.
    Umbraco.API дає можливість робити це за кількома параметрами вузла, жоден з яких до кінця не гарантує, що ми отримаємо саме той самий вузол, або отримаємо щось взагалі.

    Здавалося б, отримання вузла по його ID є ідеальним рішенням - можна захардкодіть необхідні ID і спокійно робити uQuery.GetNode (int nodeId), але в umbraco реалізована наскрізна нумерація вузлів, і, наскільки я зрозумів, не реалізований їх мержінг в разі установки пакета з тими ж вузлами. По-цьому, щоб мінімізувати роботу, пов'язану з пошуком потрібних вузлів в майбутньому, реалізований наступний механізм:

    На малюнку реалізація кастомними контрола для Umbraco. Контрол відповідає за завдання асоціацій між вузлами cms і кастомними Енума з web-додатки (DropDown мапітся на enum, вузол вибираємо через ContentPicker). Це найпростіша реалізація концепції, тобто замість Енума список назв вузлів може мати будь-яку структуру і зберігатися не тільки в Енума. Наприклад, якщо в додатку потрібно знати про 100 вузлах, а не про 10ти - можна придумати щось по-складніше. До речі, таким чином можна реалізувати і локалізацію web-сайту, додавши набори асоціацій для різних культур (стрілка Ru-Ru). Перед збереженням даних з ContentPicker'а отримуємо реальний ID вузла.

    Також при великому бажанні тут можна перевіряти, чи не пропали вузли з umbraco, очікувані в web-додатку, вивести попередження, писати мейли і т.п. передбачаючи появу NotFound-помилок.

    Дані асоціацій зберігаємо в БД Umbraco (наприклад). У найпростішому випадку таблиця має наступну структуру:

    Прикручуємо umbraco cms, як джерело даних, savepearlharbor

  • Налаштування Web-проекту
    Тепер що стосується основного проекту-споживача. Для того, щоб отримати дані, збережені через cms через api Umbraco, необхідно виконати наступне:
    • Скопіювати config \ umbracoSettings.config з кореня cms в корінь web-проекту
    • Встановити значення властивості «XmlContentCheckForDiskChanges» в цьому конфіги в true (пункт необов'язковий, але дасть можливість миттєвого «підхоплення» змін в cms)
    • Скопіювати ключі з web.config cms в web.config проекту:
      • «UmbracoDbDSN» - шлях до бази cms
      • «UmbracoContentXML» - шлях до xml-файлу, в який cms кешируєт дані. Точніше: цей файл за умовчанням знаходиться в «\ App_Data \ umbraco.config». Тут є нюанс. Якщо cms фізично розміщений на іншому сервері, то рішення задачі вимагає додаткових дій. Я не дуже глибоко вник в механізм кешування umbraco, але думаю, що при необхідності від кешування в файл можна і зовсім відмовитися.
      • Додати референс на наступні збірки:
        • businesslogic.dll
        • cms.dll
        • controls.dll
        • interfaces.dll
        • umbraco.dll
        • umbraco.DataLayer.dll

        4. Доступ до даних
        Якщо я нічого не упустив, цього достатньо, щоб api umbraco працювали, як треба. Щоб отримати потрібний вузол, потрібно знати його Id. Все, що потрібно зробити, це отримати потрібний Id з таблиці асоціацій ItemsIdMap на ім'я елемента Енума і культури, якщо така є. наприклад:

        Ось в принципі і все. Приклад цей концептуальний, в процесі виникають різні нюанси, але це вже інша історія - все вирішується в міру надходження. Також зазначу, що сам ще не тестував це рішення ні на предмет усіх можливостей, ні на предмет перформансу. До речі, в даному випадку зручно завантажити вихідні Umbraco, тимчасово підключити замість збірок і дебажіть, якщо виникають незрозумілі проблеми, тому що застосування cms нетипово. У будь-якому випадку, поки мені це рішення подобається значно більше, ніж писати админку власними руками.
        Дякую за увагу!