ORM для Sitecore своїми руками

Sitecore мало висвітлюється на хабрі, проте це дуже функціональна (і дорога) CMS досить популярна у тих, хто може її собі дозволити. Разом з тим, люди, що розробляють (і особливо підтримують) сайти на sitecore, часто скаржаться на труднощі модифікації темплейтів. Так, просте перейменування темплейту або одного поля може призвести до непередбачуваних і, головне, діагностики та виправлення порушень у роботі сайту, що важко піддаються. Причому вилізти вони можуть лише за кілька місяців. Крім того, використання стандартних сайтів Корівських FieldRenderer-ів ускладнює контроль над розміткою, що було критично в нашому випадку.

Навіщо велосипед?

Існують рішення для генерації класів на основі темплейтів (як trac.sitecore.net/CompiledDomainModel), проте вони не дуже зручні у використанні та не усувають прив'язку до структури темплейту, імен полів. Згаданий CompiledDomainModel вимагає регенераціївсіхмоделей після будь-яких змін. Також він слабо підходить для спільної розробки (постійні конфлікти в згенерованому коді), вимагає унікальних імен для всіх темплейтів, зав'язується на шляху до темплейтів та ID-шки та генерує жахливий код одним файлом (на одному з проектів там було більше 60 000 рядків та відкрити його у VS було справою дуже не швидким).

Нашій команді пощастило розробляти новий сайт під сайткор 6.3, спираючись на досвід підтримки існуючих сайтів. Відразу підкреслю, що йтиметься про контентний сайт. Цікавий функціонал був потрібний тільки в адмінці і він мало пов'язаний безпосередньо з сайткором.

Далі про форму коліс

Вирішено було уникнути прив'язки до сайткору на sublayout-ах, прикрутити строгу типізацію для темплейтів і філдів, зберігати назви філдів лише у єдиному і передбачуваномумісці.

В основі всіх наших класів-оболонок для темплейтів лежить class Template, основне завдання якого перевіряти всі існуючі темплейти Item-а та звіряти їх імена із заявленим. Для зв'язку клас-темплейт використається атрибут DataContract.

Note: тут і далі в код скорочено для передачі основної думки та легкочитаності

У тому ж класі Template є кілька корисних функцій для звернення до полів темплейту:

Наступний крок – звернення до полів. Відома проблема сайткору за підтримки сайткор-сайтів - імена полів, щедро розкидані по всьому проекту. Наше завдання мати одне і тільки одне ім'я поля в проекті. Знову використовуємо стандартні атрибути, наразі DataMember.

Найважливіше тут – функція GetFieldName, оголошена як extension-method виду:

На цьому етапі ми можемо написати щось типу:

і отримати дані з полів "Big text content"/"Logo image" поточного Item-а, за умови, що його темплейт підійде класу BaseTextPage.

Далі ми робимо обгортку для того темплейту, який буде базовим для всіх інших темплейтів. Як мінімум це буде “Standart template”, але зазвичай краще зробити щось корисніше. Наприклад

Тепер впроваджуємо все це в Sublayout-и:

З цього моменту вміст .aspx файлів починає нагадувати таку в ASP.MVC. Для посилення ефекту зручності зроблено комплект extension-методів для виведення розмітки зі стандартними перевірками на наявність/валідність даних (наприклад, не виводити картинки з порожнім src або посилання без href).

Плюси підходу: + всі потрібні поля контекстного Item-а під рукою, у вигляді властивостей + контекстний Item завжди має правильний темплейт + усі стандартні для сайткору перевірки на наявність даних зроблені в одному місці +централізоване звернення до налаштувань сайту, для яких написані аналогічні обгортки + чистий (мінімальний, відсутній) код сторінок + повний контроль верстки Мінуси — всі мапінги руками — витрати на вилучення імен полів /темплейтів