Создание кнопки на ленте с помощью Fluent Ribbon |
Дак вот, после Fluent Ribbon, на работе закодил Fluent List API, для программного создания списков. Идея примерно такая же: создаем ListDefinition, в нем - FieldDefinition'ы, потом есть ListController, ему в метод Create передаем описание списка и объект SPWeb - вуаля, список создан. Плюс там еще куча вкусных фишек, можно и представления создавать, и на заданные WebPart-страницы сразу же их выкладывать, и локализация поддерживается... В общем, пользуюсь с огромным удовольствием!
Потом была еще обертка для SharePoint Batch List API, для пакетной обработки списков. Делал для рабочих нужд, не очень универсально. Если доделаю - обязательно выложу в паблик.
Наконец, в последние дни усиленно кодю новый проект, SharePoint EcmaScript CAML Builder, предназначенный для работы с CAML запросами к спискам на стороне клиента. По задумке - это аналог знаменитого Camlex, но по синтаксису отличается: на JavaScript всё-таки нет возможности анализировать лямбда-выражения. Да и самих лямбда выражений, впрочем, там тоже нет :-)
Создание CAML-запросов с помощью CamlJS |
К слову, Camlex в серверном коде я всегда стараюсь использовать. Читабельность повышается неимоверно, и вероятность ошибки ниже. Конечно, проект не идеален: хотелось бы больше compile-time validation, но хотя бы runtime сообщения об ошибках очень внятные - уже здорово :) В общем, рекомендую!
Подводя итог, тенденция видна невооруженным взглядом. Весь CAML - нуждается в обертывании (а это, по сути дела, весь SharePoint'овский служебный XML). Но почему? Давайте разбираться.
Чтобы понять, в чем проблема, нужно заглянуть внутрь SharePoint. Если вы когда-нибудь это делали, то должны знать: центральный объект всего SharePoint'а - это некий SPRequest. Именно через этот класс в конце концов проходит, ну как минимум, вся работа с данными. А если взглянуть в этот класс, то, о ужас, обнаруживается, что это не более чем wrapper Unmanaged кода!!
Связь с мифическим ядром :) |
Да-да, оказывается, когда-то SharePoint был полностью Unmanaged проектом, и это ядро осталось с тех самых времен.
Ага, теперь-то понятно, откуда берутся все эти печально известные ошибки вида "Cannot complete this action. Please try again" :)
И если проследить путь CAML-кусков, которые мы переправляем SharePoint'у, то вы очень скоро обнаружите, что все эти XMLSchema в конечном счете передаются именно в SPRequest. Иными словами, вся обработка XML осуществляется в неуправляемом коде.
И вот в том самом мифическом ядре SharePoint'а, складывается впечатление, что существует несколько самописных XML-парзеров или препарсеров, чрезвычайно нежных и чувствительных к передаваемому им XML. По крайней мере, я ни разу не видел таких ошибок при использовании любого современного известного парсера...
Вот вам несколько ошибок XML-парзинга для примера:
- Ошибка размером в один пробел при локализации URL-полей списка.
- В элементе FieldRefs при описании ContentType не поддерживаются XML-комментарии (вообще нонсенс)
- Перенос строки в элементе Choices при описании Field приводит к проблеме в DIP при открытии документа в Microsoft Word
Итак, получаем следующее: XML-парзер явно кривоват. Но весь SharePoint завязан на CAML, без него не обойтись. Что делать? Решение естественное: генерировать код, который уж точно работает, и в котором никто не сможет уже поставить комментарий <!-- Здесь был Вася -->, и сломать всё :) Генерация позволит избежать повторяющихся ошибок, к тому же уничтожит вероятность опечаток, улучшит документированность и структурированность кода, ну и всё такое в общем :)
Мораль: используете сложный CAML-код - пишите программную обертку.
Нет, это рабочий проект, он создавался по большей части в рабочее время, к тому же заточен под использование в конкретном проекте.
ОтветитьУдалитьА зачем писать свою обертку поверх CAML, если она уже есть под названием LinqToSharePoint?
ОтветитьУдалитьEugene, ну во-первых, CAML это не только CAML Query. CAML Query это лишь малая часть CAML.
ОтветитьУдалитьСоздание списков, их определений, представлений, страниц, заполнение страниц, плюс все эти Custom Actions - да собственно весь вот этот настроечный XML, который есть в SharePoint (всё что мы пишем в Elements.xml, schema.xml, onet.xml), это всё и есть CAML.
Что касается Linq-To-SharePoint, к сожалению первая реализация этого функционала очень далека от идеала. Печально известная "проблема первой версии", надо полагать. В общем, для серьезных задач использовать Linq-To-SharePoint довольно сложно, лично мне ничего путного с ним добиться не удалось, хотя много в этом направлении копал, и даже например использовал плагинную реализацию Model-First для Linq-To-SharePoint - это уже удобнее чем SPMetal, но вообще все сейчас идут к Code-First, и я надеюсь что в SharePoint ребята придут туда же.
В общем, на мой взгляд, Linq-To-SharePoint еще пока не готов для серьезных проектов.
Я имел ввиду CAML запросы на обработку данных и Работу со списками как с типизированными коллекциями. Какие там серьёзные задачи неудаётся сделать не понятно. Файлы которые генерит SPMetal - да, приходится править ручками что бы нормально потом работать с классами.
ОтветитьУдалитьПро CAML Query:
ОтветитьУдалитьЧто касается неудобства применения LinqToSP для работы с данными списков/библиотек не убедительно. Подводных камней там уйма. Приведи хоть один реальный пример.
Про CAML Definitions:
Чтобы завернуть CAML декларации в код, надо много писать кода, а времени на это на проектах никогда нет. CAML конечно плох, но его не обойти никак. Если за пример брать твой FluentRibbon то мне очень нравится решение. Но вот для FluentListAPI я не могу придумать сценариев применения.
Про статью:
Ты пишешь, что надо писать обертки, потому что CAML обрабатывается неуправляемым кодом.
Теперь берем FluentListAPI и проследим метод AddFieldToList() класса ListController. Он все равно вызывает стандартные методы шарика, которые в свою очередь формируют CAML и отправляют его в SPRequest.
За что боролись, на то и напоролись.
Zhukov, в статье как раз и написано что без CAML не обойтись. Обертывание нужно, чтобы не давать девелоперам напрямую работать с CAML, чтобы минимизировать число гейзенбагов, и всяких нелепых ошибок/опечаток.
ОтветитьУдалитьЕсли взять такой сценарию:
ОтветитьУдалитьесть SiteDefinition, который содержит в себе ContentType, ListTemplate и ListInstance.
Ты считаешь, что все это содержимое должно быть описано в коде и деплой должен происходить в EventReceiver'е?
Мысль конечно интересная. А были у тебя проекты, где ты (или не ты) успешно это применял?
Zhukov, угу, проект называется DeskWork.ru :) Используем очень активно по всему проекту. От развертывания через CAML вообще сознательно отказались, из-за проблем с обновлениями - выделили время и переделали. Раньше было всё на CAML, сейчас всё развертывается только программно.
ОтветитьУдалитьПолучается что каждый работает со своим такие фреймворком, TOPSbi со своим,Terralink со своим CAML генератором Softline тоже частично со своим и каждый свой фреймфорк хвалит))
ОтветитьУдалитьEugene, мне кажется наличие программных оберток и альтернативных CAML-решений как раз и обусловлено неудобством использования нативного SharePoint'овского API в имеющемся виде, и отсутствием хороших бесплатных решений для этой проблемы.
ОтветитьУдалитьНаписание оберток для SharePoint'а и наверное для любой другой платформы - это неизбежно и совершенно логично. Всегда найдется какое-нибудь неудобство, которое стоит сделать удобным и сэкономить тем самым много времени и сил. SharePoint - очень широкая и многообразная платформа, что-то там сделано хорошо, но далеко не все.
P.S. Что касается Softline, хотя я там на текущий момент работаю (а кроме меня - еще 1700 человек), в данном блоге я представляю самого себя. Прошу не отождествлять :)
Andrey Markeev, насчет обертки для CAML, полностью с тобой согласен, сам на второй месяц знакомства с SharePoint, написал обертку (этакий CAMLutility) и таскаю его из проекта в проект, оптимизируя и "долизывая" ))
ОтветитьУдалить