Страницы с тегами : SharePoint

Встреча сообщества по SharePoint и Office 365

26 октября 2016 года состоится встреча сообщества по SharePoint и Office 365. Поделимся опытом реализации проектов на SharePoint и расскажем про новые возможности Office 365. Встреча пройдет в Microsoft Technology Center на Лесной. Начало встречи в 18:00.



SharePoint 2016 для архитекторов

Месяц назад SharePoint 2016 стал RTM. Это значит, что изменений в функционале SharePoint в ближайшие полгода мы не увидим.

SharePoint 2016 еще не GA (General Availability), то есть вы не сможете получить полноценный лицензионный ключ, только триал. Но уже пора думать о переходе на новую версию.

В SharePoint 2016 мало изменений с точки зрения пользователя или разработчика, зато много с точки зрения администратора и архитектора.

Подробнее рассмотрим новшества.



Встреча сообщества по SharePoint и Office 365

7 апреля 2016 года состоится встреча сообщества по SharePoint и Office 365. Будем обсуждать SharePoint 2016, который недавно стал RTM. На встрече расскажем про новые фичи, особенности миграции и апгрейда, project server и DSC. Встреча пройдет в Microsoft Technology Center на Лесной. Начало встречи в 18:30.



SharePoint TypeScript теперь на github

SharePoint TypeScript - проект для описания типов TypeScript клиентской библиотеки SharePoint. Это не только JavaScript Object Model, но описания типов для Client-Side Rendering (CSR) - движка для рендеринга форм и представлений, а так всевозможных клиентских компонент.



Записи докладов по Business Intelligence c DevCon 2014

На конференции DevCon, которую ежегодно организует Microsoft, в 2014 году я выступал аж с двумя докладами, оба были на тему Business Intelligence в SharePoint.

Недавно были опубликованы видеозаписи. Выложу их в блоге, чтобы проще было найти.

Первый доклад по Power Pivot в SharePoint 2013 (on-premises), в котором я показываю пример мини-erp решения для управленя отделом, которое можно собрать за несколько часов совершенно без программирования.

Второй доклад посвящен возможностям PowerBI в Office 365. Особое внимание было уделено инструменту Power Query, его использованию в Excel, а также настройке гибридной среды для получения доступа из облака к данным on-premises.

А вы используете в своей работы BI инструменты SharePoint? Напишите в комментах в каких сценариях применяли или почему не применяли.


Загрузка скриптов в SharePoint

В прошедшем недавно семинаре про клиентской разработке в SharePoint (записи – по ссылке) я показывал как сделать клиентский скрипт, который выполняет некоторый код после окончания загрузки страницы в SharePoint.

Эта, казалось бы, простая задача далеко не тривиально реализуется в SharePoint.

Причины

    1. SharePoint формирует интерфейс динамически. Многие блоки добавляются на страницу по событию body.onload. Это событие возникает позже, чем DOMContentLoaded. Именно это событие перехватывает jQuery.ready. Поэтому использование jQuery часто не приводит к хорошему результату. Подробнее об использовании jQuery в SharePoint.
    2. Minimal Download Strategy (MDS), появившийся в SharePoint 2013, загружает страницу один раз, потом обновляет блоки страницы, поэтому нужно выполнять дополнительные действия, чтобы скрипт выполнился после загрузки страницы под MDS.
    3. Механизм загрузки скриптов, о котором я писал ранее, требует чтобы скрипт самостоятельно оповещал об окончании выполнения.

Для скриптов в виртуальной файловой системе SharePoint

Чаще всего скрипты SharePoint деплоятся как файлы в виртуальной файловой системе. Это прекрасно работает как в on premises, так и в online.

Для размещения скриптов на странице используется контрол ScriptLink, в таком виде:

<SharePoint:ScriptLink Name="autofill.js" runat="server" OnDemand="true" LoadAfterUI="true" Localizable="false" />

или с помощью CustomAction ScriptLink в элементе решения

<CustomAction Location="ScriptLink" ScriptSrc="~site/Extensions/typescripttemplates.js" />

Внутри скрипта нужно выполнить следующие действия:

  1. Оповестить SharePoint об окончании загрузки.
  2. Добавить функцию, которую необходимо вызывать после загрузки страницы, в массив _spBodyOnLoadFunctions.
  3. Добавить зарегистрировать скрипт в системе MDS.

Код:

// IIFE для изоляции
(function () {
    "use strict";


                
            


Я выступаю на DevCon 2014

Немного запоздалый, но все же анонс.

28 и 29 мая я буду выступать на конференции DevCon 2014. В этот раз у меня целых два доклада. Первый (28 мая в 17:10) на тему новых возможностей BI в SharePoint 2013, где я буду рассказывать рол PowerPivot и PowerView. Второй доклад (29 мая в 10.30) про BI в облаках с применением PowerBI и Office 365.

Приходите на доклады, кто будет присутствовать на конференции или смотрите трансляцию.



10 вещей, которые надо знать при использовании jQuery в SharePoint

Для чего нужен jQuery в SharePoint? Обычно его используют для четырех целей:

  • Вызывать код JavaScript в момент загрузки страницы с помощью $(document).ready.
  • Использовать Ajax функции для доступа к данным на сервере.
  • Использовать готовые плагины,такие как tooltip или tabs, для того, чтобы расширить функционал сайта.
  • Проводить некоторые манипуляции с объектной модели документа (DOM).

Если Вы собираетесь использовать jQuery на страницах SharePoint, то вам нужно знать следующие вещи:  

 

1. Используйте mQuery и RequestExecutor в простых случаях

Если у вас простой случай, то Вы можете использовать библиотеку mQuery для манипуляции DOM и RequestExecutor для ajax запросов. Кроме того, вместо Ajax запросов гораздо выгоднее использовать JSOM и TypeScript для клиентской разработки. Об этом я писал ранее.

Если Вы, все таки, решили использовать jQuery, то вам нужно помнить следующее:

2. jQuery(document).ready срабатывает не вовремя

Это происходит потому, что $(document).ready взрывается при событии DOMContentLoaded. А это события создано для тех случаев, когда весь контент страницы загружается с сервера. Оно происходит после того как браузер скачал всю страницу, связанные файлы и всё распарсил. SharePoint использует механизмы динамического формирования страницы, когда скрипты в теле страницы запускаются и формируют части страницы. В этом случае использовать DOMContentLoaded, отрабатывает до того как сформирована страница. Гораздо более надежный способ вызова после загрузки страницы – с помощью события body.onload. Для этого в SharePoint есть готовые функции.

 

3. Используйте _spBodyOnLoadFunctions или _spBodyOnLoadFunctionNames

Эти два массива (да-да, обычные JS массивы). _spBodyOnLoadFunctionNames содержит имена глобальных функций, которые необходимо вызвать на событие body.onload. _spBodyOnLoadFunctions содержит объекты-функции, что гораздо удобнее, но доступно только в SharePoint 2013. Кроме того есть переменная _spBodyOnLoadCalled, которая равна true, если функции уже были выполнены.

Пример:

(function() {
    if (!_spBodyOnLoadCalled) {
        _spBodyOnLoadFunctions.push(pageLoad);
    } else {
        pageLoad();
    }


                
            


Видеозаписи докладов с ноябрьской встречи RUSUG

Внезапно у меня оказались записи докладов со встречи, которая проходила 25 ноября 2013 года.

Доклад Михаила Бондаревского.

 

Доклад Сергея Слукина.



Онлайн курсы и материалы для изучения SharePoint

Про изучение SharePoint 2010 для разработчиков и администраторов я писал два с половиной года назад, почти все материалы до сих пор доступны:

В SharePoint 2013 появилось много новых возможностей. Теперь для разработчика недостаточно просто уметь писать веб-части и event receivers. В SharePoint 2013 поставить ферму для разработки – само по себе требует многих навыков, а разработчику надо еще как минимум уметь настраивать поиск, управляемые метаданные, профили пользователей, apps и workflow.

Чистая разработка для SharePoint 2013 идет в сторону apps (ASP.NET), но закрывает лишь малую часть потребностей заказчиков. Навыки развертывания, администрирования и использования стандартного функционала оказываются для разработчиков чуть ли не важнее навыков писать код.

Поэтому я не буду разделять курсы для разработчиков и администраторов. Для профессионалов, создающих решения на SharePoint, они одинаково важны.

Далее ссылки на курсы и каталоги материалов, которые можно использовать для самостоятельного изучения:

  1.  http://technet.microsoft.com/en-US/sharepoint/fp123606 - SharePoint 2013 training for IT pros.
  2. http://msdn.microsoft.com/en-US/office/dn448488 - Office 2013 developer training videos. Пусть не пугает называние, большая часть курса – по SharePoint 2013.
  3. http://www.microsoft.com/resources/Technet/en-us/Office/media/ITProPivotViewer/ – интерактивный браузер всего контента Technet.
  4. http://technet.microsoft.com/en-US/projectserver/jj906608 - Project 2013 training for IT pros and developers.
  5. https://channel9.msdn.com/Events/SharePoint-Conference/2012 – видео с конференции SharePoint Conference 2012, в докладах часто можно встретить темы, отсутствующие в документации.
  6. http://pluralsight.com/training/Courses#sharepoint – Pluralsight, крайне рекомендую. За $300 в год (меньше цены одного курса в УЦ) вы получите 99 (на сегодня) и более (в будущем) курсов по SharePoint 2007-2013. Некоторые из них содержат уникальный контент, который более нигде не доступен.
  7. http://www.microsoftvirtualacademy.com/Studies/SearchResult.aspx?q=SharePoint – курсы на Microsoft Virtual Academy, есть очень полезные курсы с глубоким погружением в тему.
  8. http://code.msdn.microsoft.com/officeapps/Apps-for-SharePoint-sample-64c80184 - Примеры приложений для SharePoint, увы, код не всегда рабочий.
  9. http://social.technet.microsoft.com/wiki/contents/articles/14579.sharepoint-2013-books-a-comprehensive-list.aspx – список книг по SharePoint 2013, но если вы изучите все по ссылкам выше, то вам надо будет только прочитать Inside SharePoint 2013.
  10. http://spf2013faq.mindsharp.com/Lists/SharePoint%202013%20Books%20and%20Extracts/V%20Books.aspx – тоже список книг.

Для начала хватит. Как обычно нужно много и внимательно читать MSDN и TechNet.

Изучайте, пользуйтесь, создавайте хорошие решения.



Поиск в приложениях SharePoint. Часть 3.

В SharePoint 2013 появился REST веб-сервис, который позволяет делать поисковые запросы из JavaScript. В SharePoint 2010 есть только search.asmx, который требует генерировать и парсить большой объём XML (в лучших традициях SharePoint).

Чтобы упростить жизнь разработчику клиентских компонентов я написал REST веб-сервис для SharePoint 2010.

Реализация

За основу взял метод, который описывал ранее - Javascript-enabled SharePoint WCF services.

Контракт у сервиса очень простой:

[ServiceContract]
public interface ISearch
{
    [OperationContract]
    [WebGet(BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    Stream Query(string q, int top, int skip, string select, string orderBy, bool includeRefiners, string refiners);
}

Параметры вызова:

  • q – текст запроса (обязательно).
  • top – количество результатов.
  • skip – с какой позиции в выборке отдавать результаты.
  • select – через запятую названия managed properties в результатах.
  • orderBy – через запятую названия managed properties по которым сортировать результат, после имени можно указать desc для сортировки по убыванию.
  • includeRefinerstrue или false, возвращать результаты уточнений или нет.
  • refiners - через запятую названия managed properties для формирования уточнений.

Реализация:

public System.IO.Stream Query(string q, int top, int skip, string select, string orderBy,
                    bool includeRefiners, string r) 
{
    using (new SPMonitoredScope("Execute Query Method"))
    {
        var site = SPContext.Current.Site;
        var result = GetSearchResults(site, q, top, skip, select, orderBy, includeRefiners, r);
        return ToJson(result);
    }
}

Метод GetSearchResults довольно простой, он передает параметры запроса в объект KeywordQuery и получает результат.

private static ResultTableCollection GetSearchResults(SPSite site, string q, int top, int skip, string select, string orderBy, bool includeRefiners, string r)
{
    var query = new KeywordQuery(site);
    query.QueryText = q;
    query.StartRow = skip;
    if (top > 0)
    {
        query.RowLimit = top;
    }


                
            


Масштабирование ECM на SharePoint

Бытует мнение, что на для построения масштабируемого ECM решения на SharePoint  требуется глубокая кастомизация и без нее никуда. Причин этому много: широко известные Large List Threshold, тормознутые разрешения, Security Scopes Limit, довольно слабые возможности создания связей между элементами, ненадежный и невыразительный движок Workflow.

Тем не менее, при правильном подходе, можно построить ECM систему, хранящую терабайты документов, без тяжелой разработки.

Принципы

Первая и самая важная ошибка, которую совершает большинство разработчиков – использование хранилища SharePoint, как реляционной СУБД. В РСУБД тип данных соответствует расположению (таблице). При переносе этого принципе в SharePoint все документы, независимо от стадии их жизненного цикла, помещают в одну библиотеку. При такой архитектуре решение валится от нагрузки еще до достижения каких-либо лимитов.

В SharePoint тип данных задается типом контента. Типы контента не привязаны к спискам и могут располагаться где угодно. Более того, документы в SharePoint легко могут перемещаться между списками, сайтами и даже коллекциями сайтов, в том числе в разных контентных базах данных на разных серверах. Этим надо пользоваться при построении решений.

Первый принцип ECM в SharePoint, который обязательно нужно применять с самого начала – разделять оперативные и архивные документы. Обычно объем оперативных документов составляет не более 20% от общего объема и со временем этот показатель уменьшается. Если в РСУБД архивность - это не более чем атрибут, то в SharePoint надо явно задавать политики, по которым документы будут перемещаться в архив.

Сразу же возникает проблема,  как собрать все документы одного типа из разных расположений. В этом помогает поиск SharePoint. Поиск SharePoint позволяет строить сложные выборки и получать статистику.

Второй принцип ECM в SharePoint – использовать возможности поиска для построения выборок “всех” документов. “Всех” специально взял в кавычки, так как обычно нужны не все документы, а некоторая выборка по критериям. Для базовой реализации хватает встроенных возможностей SharePoint, сложные вещи потребуют разработки веб-частей, которые будут строить сложные поисковые запросы.

Третий принцип ECM в SharePoint, самый сложный для применения – не пытаться создать универсальную модель сущностей и связей для всего ECM, а сконцентрироваться на автоматизации конкретных процессов. Люди с аналитическим складом ума всегда пытаются обобщить механизмы работы системы, чтобы уменьшить её когнитивную сложность. Это, в свою очередь, ведет к усложнению реализации из-за частных случаев и процессов выбивающихся из общей картины. Нужно понять, что пользователям не придется сталкиваться со всей системой разом, они будут работать с малой частью системы в один момент времени. Для начала нужно исключить из лексикона слова “любой” и “все”, всегда рассматривать конкретные процессы и типы документов.

Инфраструктура

Когда разобрались с принципами нужно правильно подготовить инфраструктуру к реализации системы. Если вы еще не перешли на SharePoint 2013, то самое время это сделать. Также вам понадобится Exchange для электронной почты.

Для работы вам обязательно понадобятся четыре службы:

  • Служба поиска
  • Служба управляемых метаданных
  • Служба профилей пользователей (должен быть настроен импорт из AD)
  • Служба управления приложениями (App Management Service)

Эти службы должны работать и быть правильно настроенными, чтобы все возможности были доступны.

Обязательно нужно поставить и подключить к SharePoint серверы Workflow Manager и Office Web Apps.

На ферме SharePoint обязательно надо настроить исходящую и входящую электронную почту, а также создание групп рассылки в AD, чтобы можно было отправлять почту группам

Далее вам понадобится как минимум три коллекции сайтов (не считая коллекции сайтов портала, MySiteHost и App Catalog):

  • ECM Control Center – коллекция сайтов с включенными фичами Content Type Syndication Hub и Document ID. Шаблон может быть любой. В службе управляемых метаданных необходимо вписать url этой коллекции в поле Content Type Hub (подробнее - http://www.wictorwilen.se/Post/Plan-your-SharePoint-2010-Content-Type-Hub-carefully.aspx)
  • Архив – коллекция сайтов из шаблона Центр Записей (Records Center). Архив желательно разместить в отдельной БД и настроить Remote Blob Storage.
  • Коллекция сайтов с оперативными документами. В зависимости от информационной архитектуры фермы может быть несколько таких коллекций. Рекомендую сразу включить и настроить фичу Document ID в этих коллекциях.

В настройках фермы создайте подключение для отправки документов (Send To Connection) и укажите в качестве назначения урл организатора контента в коллекции узлов архива (Подробности тут: http://office.microsoft.com/en-gb/office365-sharepoint-online-enterprise-help/configure-send-to-connections-for-records-management-HA102895194.aspx).

Кстати это все доступно и в Office 365, вам необходимо будет только создать коллекции сайтов архива и оперативных документов. Для content type hub автоматически создается коллекция узлов, не видимая в списке в панели администрирования.

Схема данных

Когда ферма готова надо начинать описывать типы контента документов. Все типы контента необходимо создавать в ECM Control Center. После создания типы контента необходимо опубликовать и механизмом синдикации эти типы будут копироваться в остальные коллекции сайтов вместе с полями, формами, шаблонами документов и политиками.

Надо учитывать, что lookup поля не поддерживаются при синдикации, поэтому все лукапы надо заменить на поля выбора, поля метаданных или ссылки на DocID (придется сделать custom renderer).

Рабочие процессы

Когда необходимые типы контента созданы и опубликованы можно приступать к созданию процессов.

Процессы  могут быть двух видов:

  • Структурированные – когда есть схема и четко прописаны роли.
  • Ad-hoc процессы – когда набор участников задается при запуске процесса, а маршрут заранее не определен или определен частично.

Для Ad-hoc процессов удобно использовать встроенные в SharePoint рабочие процессы утверждения и сбора отзывов. Важно следить чтобы ad-hoc процессы работали в рамках небольшой группы людей, иначе процессы будут очень сильно буксовать.

Структурированные процессы могут затрагивать людей из разных подразделений и выполняться довольно долго, а также содержать нетривиальную логику ветвления. Для таких процессов имеет смысл использовать workflow в режиме SharePoint 2013, созданные в SharePoint Designer и, возможно, допиленные в Visual Studio.

Для структурированных процессов необходимо создать группы SharePoint под каждую роль в процессе. Это сильно упростит вопросы замещения отсутствующих пользователей и делегирование обязанностей (достаточно будет добавить человека в группу).

Для каждого процесса необходимо создать свой список с нужным типом контента и цеплять рабочие процессы к этому списку. Для каждой группы процессов, сходных по целям, создавайте отдельный сайт. Например для согласования договоров отдельный сайт, с несколькими списками: договоры с подрядчиками, договоры с клиентами; для командировок свой сайт, и так далее. Landing page сайтов наполните инструкциями о том, как работать с процессами. Желательно запишите видео.

Типы контента, полученные с помощью синдикации, являются read-only. Но в списки и библиотеки можно добавлять поля, помогающие автоматизировать процессы. Также в списках можно создавать папки для разграничения доступа.

Важно везде использовать ссылку на Document ID, вместо url файла.

Архивирование

Так как большая часть списков и библиотек в оперативных коллекциях сайтов будут иметь плоскую структуру, то они быстро превратятся в помойку. Надо настроить автоматическое архивирование с помощью политик жизненного цикла (retention policy). Их можно цеплять как к типам контента, так и к библиотекам или папкам. Например можно назначить политику – перемещать в архив документы через месяц (неделю, год, на ваше усмотрение) с даты последнего изменения. (подробнее тут - http://www.c-sharpcorner.com/uploadfile/anavijai/retention-policy-for-a-document-library-in-sharepoint-2010/). Кроме того операцию перемещения в архив можно добавить в виде действия рабочего процесса.

В Архиве необходимо настроить Content Organizer, чтобы он размещал документы по папкам. Content Organizer умеет раскладывать документы по подпапкам в зависимости от атрибутов типа контента, а также умеет создавать подпапки при достижении границы количества элементов (чтобы исключить Large List Threshold).

Еще одна возможность, которой обязательно надо пользоваться – “объявление записью”. По сути это полная блокировка изменения документа. В архиве можно настроить автоматическое объявление записью всех попадающих в него документов.

Поисковые представления

В SharePoint 2013 колонки сайта автоматически превращаются в managed properties поиска. Но, увы, без атрибута refinable. Поэтому для начала вам надо будет создать в схеме поиска нужные managed properties. Также удобно создать типы результатов (Search Result Type) под каждый тип документа.

После этого можно сделать отдельный сайт – центр поиска, на котором разместить поиск по всем документам и, при необходимости, по отдельным типам.

Заключение

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



Как поставщики решений SharePoint обманывают заказчиков

На днях получит вот такой коммент в обсуждении на Хабрахабре:

Государственный университет в регионе N хочет себе СЭД, пользователей на 100. Кроме СЭД хочет простенький портал, телефонную книгу, новости, календарики.
На Sharepoint Server денег тратить не хочется, да и нет необходимости — рейтинги, социальные сети, политики хранения контента не в почете у сотрудников.
Поэтому решили купить СЭД на Foundation, заплатив только за СЭД-надстройку (будем считать что лицензионные права на Foundation у них уже есть).


За 2-3 года документов скопилось около 60-80 тыс. (по всем группам). По ним нужно, в самом простейшем случае:
а) осуществлять быстрый и легко настраиваемый поиск (по конкретным атрибутам и без управляемых метаданных) по любым элементам и с учетом прав
б) быстро искать и исполнять задачи. задач при этом становится = (кол-во документов * 5)

Если знаете способ реализовать это на Foundation «изкаропки», пожалуйста, расскажите, очень интересно.

Исходный пост и обсуждение можете почитать по ссылке: http://habrahabr.ru/post/210844/#comment_7260770

Используя SharePoint Server, даже версии Standard, можно настроить быстрый и удобный поиск по документам и задачам. Это даже не потребует программирования, достаточно будет за день-два выполнить настройку поисковых представлений.

Решение, предлагаемое автором коммента, требует создания баз данных, custom service applications, собственного интерфейса пользователя и кода для привязки к стандартному функционалу. При очень хорошем раскладе такая разработка займет около двух недель.

Кажется, что решение на Foundation действительно выгоднее. Но на самом деле это обман.

Считаем стоимость

Так как решение делается для Государственного Университета, то стоимость лицензий на продукты Microsoft будет примерно в 10 раз ниже среднерыночной.

Я зашел на сайт http://www.msbuy.ru/ (не реклама, просто первый удобный калькулятор из выдачи гугла) и посчитал полный объем лицензий:

  • SharePoint Server – 1 шт
  • SharePoint Server Standard CAL  – 100 шт (на пользователя)
  • SQL Server Standard Core – 2 шт (4 ядра) 

У меня получилось 797 182.84 рублей. Лицензии на Windows Server не считал, так как они также нужны для Foundation. Для госуниверситета цена выйдет около 80 000 рублей. SharePoint Foundation, работающий на SQL Express, обойдется фактически бесплатно.

Даже если взять самых дешевых специалистов SharePoint, то их стоимость для заказчика составит не менее $60\час. Для SharePoint Server понадобится 16 часов работ по настройке представлений, для Foundation объем работ вырастет до 80 часов.

В деньгах:

  • Server – 16 часов =  $960 = 33 600 рублей.
  • Foundation – 80 часов = $4 800 = 168 000 рублей.

Внезапно решение на Foundation оказалось дороже, чем на Server, даже с учетом цены лицензий последнего.

Но и это еще не все.

Совокупная стоимость владения

Нужно понимать, что расчет выше касается одного аспекта функционала. Зачастую в решениях на Foundation создается много кода, имитирующего стандартный функционал платной версии SharePoint - поиск, профили пользователей (для хранения данных о пользователе), управляемые метаданные (структурированные справочники) и жизненный цикл документов. Например в SharePoint Standard справочник сотрудников (aka телефонная книга) и новости на портале можно сделать за два часа прямо в браузере. Подобное решение на Foundationобойдется в пару тысяч долларов минимум. В совокупности решение на Foundation, начинает стоить на порядок больше, чем решение на платной версии.

Вполне возможно, что поставщик решений в таком случае будет пытаться продать “продукт”, с уменьшенной начальной ценой, но с сервисным контрактом, по которому за три года объем выплат превысит стоимость разработки. Неопытным покупателям кажется что сервисный контракт является необязательным, но  без него решение свалится и никто не сможет его поднять, а поменять какую-нибудь мелочь смогут только разработчики. Поэтому сервисные контракты не покупают только те, кто фактически не пользуются решением.

Обязательно стоит учитывать скрытую стоимость решений. Подробнее тут - http://gandjustas.blogspot.ru/2013/07/sharepoint.html.

С другой стороны платная версия SharePoint содержит много функционала, который можно использовать без кастомизации: поиск по внешним системам, мощные рабочие процессы согласования, совместное редактирование документов, личные узлы и удобный шаринг.  Даже если не рассматривать скидку на лицензии в 90%, как для Государственных Учебных заведений, то амортизированная стоимость лицензий на одно решение оказывается гораздо ниже. Кроме того, есть программы лицензирования, по которым цена лицензий оказывается значительно ниже.

Как продают впаривают

Тоже процитирую комментарий из обсуждения:

СЭД — это не портал. Принципы разграничения прав не по элементам, а по карточкам документов, например. То же самое и при отображении. Документ в СЭД — это же не просто элемент в списке или библиотеке, это элемент, связанный с кучей всего, вроде связанных файлов, других документов, журналов, поручений (которые еще связаны с задачами). Принципы работы довольно сильно отличаются. XXX for Sharepoint нужны как раз для адаптации Sharepoint к российскому документообороту, чего из коробки никак не сделать.

Мне, как техническому специалисту, это кажется смешным. В SharePoint Standard есть наборы документов, которые позволяют связывать несколько документов в одно целое, для связанных журналов и поручений нужно делать отдельные папки в списках, чтобы можно было давать доступ сразу на группу элементов. Всю автоматизацию моно сделать в workflow или с помощью небольших кусков кода. Это абсолютно не требует баз данных, custom service application и подобных “тяжелых” кастомизаций.

Но обычный заказчик об этом не знает. Ему откровенно врут, что никак нельзя сделать стандартными средствами и обязательно нужно купить дорогую кастомизацию, чтобы все было как он захочет. При этом, конечно же, не случается так, как хочет заказчик. Но выхода у него нет, ему помогли “сэкономить”, поставив Foundaton, и теперь заказчик вынужден доплачивать вендору, чтобы действительно стало как он хочет.

Заключение

Если вам предлагают решение, которое работает на Foundaion, то вас скорее всего разводят. Оно окажется не только более дорогим по совокупной стоимости владения, но и вы попадете в сильную зависимость от вендора решения и будет сложно переключиться.

Я понимаю, что есть и хорошие решения на Foundation, которые действительно делают что-то, что не умеет SharePoint Standard или Enterprise. Но таких решений очень мало, особенно на Российском рынке. А также вам надо удостовериться, что они идеально вам подходят, ибо доработка будет дорогая.



Успех проекта SharePoint, где он?

Есть статистика, которая говорит, что более половины SharePoint проектов неуспешны (смотреть тут). С точки зрения бизнеса успешных проектов еще меньше, так как затраты оказываются выше, чем экономический эффект.

Проблема

Многие проекты SharePoint фактически ведутся по процессам разработки программного обеспечения. Все процессы разработки ставят целью разработку нового или доработку существующего ПО. Основные KPI для такого проекта – сроки, функциональный объем и бюджет. Еще говорят о качестве, но качество померить сложно и оно как-то выпадает из основных характеристик.

Негативным эффектом такого способа ведения проектов становится то, что создается много кастомного кода. Ведь нельзя делать разработку, когда нечего положить в систему контроля версий. Обучая разработчиков out-of-the-box функционал, я много раз слышал вопрос о том, что же будет в итоге лежать TFS.

Кастомный код при этом является огромной проблемой, он усложняет поддержку портала, появляются проблемы при апгрейде и попытках развития решений. Зачастую именно кастом код является причиной падений SharePoint и низкой производительности.

Казалось бы, почему просто не использовать правильную методологию? Оказывается такой методологии нет. Все что можно найти на просторах интернета – адаптация процессов разработки для SharePoint.

Как добиться успеха

В первую очередь надо фокусироваться не на поставке функционала, а на увеличении value от внедрения. Причем этот самый value надо не просто определить, а измерять. Проект считается законченным, когда достигнуты целевые показатели (KPI, связанные с value), это может случиться сразу после поставки функционала (маловероятно), а может и через год (более вероятно). План проекта должен отражать действия для достижения KPI, а не работы по созданию ПО.

Возможен и негативный вариант, когда затраты на проект растут быстрее, чем value, измеряемый в деньгах. В этом случае надо “фиксировать убытки” и закрывать проект.

Из этого следует второй принцип – делайте проекты маленькими. Чем меньше проект, тем быстрее можно достичь целевых KPI и тем меньше возможный убыток. Маленькие проекты проще запускать и проще убивать. Чем меньше проект, тем проще он поддается изменениям. Маленький проект гораздо проще аутсорсить, если своих ресурсов недостаточно. При этом можно увеличивать число проектов, запуская многие из них параллельно.

Например, вместо огромного проекта “создания корпоративного портала” на полтора года и тысячи человеко-часов, можно запустить с десяток мелких проектов, каждый со своими KPI. Буквально через месяц по каждому проекту станет ясно имеет ли смысл его продолжать.

Может казаться, что это очень сильно увеличит нагрузка на менеджера. Если вам приходилось управлять двумя-тремя проектами сразу, то десять проектов может показаться адом. Но оказывается есть зубры, которые могут управлять и 50 проектами - http://www.linkedin.com/groups/How-many-projects-can-project-37888.S.210671311. Сказывается эффект масштаба – чем больше проектов, тем проще управлять каждым в отдельности.

Последнее, но самое важное тем не менее - минимизируйте объем кастом кода, особенно при работе с server-side object model. Чем больше кода, тем дороже поддержка, тем меньше шанс на успех.

Заключение

Я понимаю, что для многих очень сложно перестроить мышление с одного большого проекта на кучу мелких, но это просто необходимо сделать. Если сложно сделать сразу, то отрезайте от большого проекта маленькие независимые кусочки и запускайте их по отдельности.



Простой способ повысить качество решений

image
Наверное каждый из вас сталкивался с такими решениями для SharePoint: решение вроде работает, но постоянно возникают какие-то проблемы, данные не сохраняются, странные падения при, казалось бы, безобидных операциях. Тестеры тратят много времени на такое решение, но исправление одних багов порождает другие. Развернуть такое решение на production ферме оказывается очень сложно, поддержка превращается в ад. Знакомо, да?

Занимаясь разработкой правил анализа кода для SPCAF (http://spcaf.com), я нашел способ как быстро исправить такую ситуацию.

Найдите все блоки кода такого вида:
try
{
    //код
}
catch(Exception e)
{
    //здесь что угодно, кроме throw;
}

Впишите throw; в блок catch. Важно что в catch указывается базовый Exception, а не конкретный тип исключения.
Ваше приложение начнет падать и вам надо будет исправить все найденные ошибки, не убирая throw. Я такое уже проделывал много раз на разных проектах, и это давало очень положительных результат. Даже если программисты будут сопротивляться, не допускайте убирания throw.

Исследование


Для тестирования правил я собрал около 70 .wsp файлов, решений SharePoint. Большинство из них — проекты, в которых мне довелось участвовать, и я прекрасно знаю все проблемы, которые возникали при разработке. Я посчитал плотность блоков try\catch без throw и вот что получилось:
  • Самое проблемное решение — 1 блок на 36 строк. То есть почти каждый значимый метод был завернут в такойtry\catch.
  • Решения средней паршивости — 1 блок на 90-100 строк. В некоторых из этих решений уже были проведены чисткиtry\catch.
  • Хорошие решения — 1 блок на 120-130 строк. С ними никогда не возникало проблем.

Обоснование


Перехват всех исключений не рекомендуется практически всегда, на него ругается Visual Studio Code Analysis, об этом написано в Framework Design Guidelines. В книге Pragamtic Programmer, которую стоит прочитать всем без исключения программистам, коротко и емко сформулировано правило — Crash, don't Trash.
Фактически перехват всех исключений это попытка подавить ошибку, допущенную программистом. Ошибка все равно вылезает, но не так очевидно и, зачастую, в совершенно другом месте. Это и создает проблемы при разработке решений. Особенно сильно это проявляется для SharePoint, так как его API крайне сложен.
Я знаю только один случай в решениях SharePoint когда оправдано ловить все исключения и не выбрасывать их дальше — в визуальных компонентах, чтобы ошибка разработчика не завалила портал. Но даже в них стоит рассмотреть обработку конкретных типов исключений, вместо перехвата всех подряд. В остальных случаях код должен падать максимально быстро и громко, желательно сообщая о том, что пошло не так. Не надо делать никаких возвратов false или null в случае исключения, пусть код упадет, тогда разработчики и тестеры увидят ошибку, до того как её увидит пользователь.

 

Заключение


Проблема подавления ошибок актуальна не только для SharePoint решений и не только на языке C# и платформе .NET. Возможно и в других проектах вы сможете значительно улучшить ситуацию убирая подавление исключений.
PS. Набор правил, которым проверял решения — http://spcafcontrib.codeplex.com/


Релиз SPCAF Contrib

Для тех кто не в курсе что такое SPCAF. SPCAF – аббревиатура SharePoint Code Analysis Framework, инструмент позволяющий проводить проверки кода решений SharePoint и собирать полезные метрики. SPCAF состоит из четырех компонент: SPCop, SPMetrics, SPInventory, SPDependency. Первый компонент распространяется отдельно и бесплатно. Весь SPCAF стоит 2500 евро (очень дорого).
SPCAF создавался для крупных компаний, которые работают с кучей подрядчиков, и для них очень актуальна проблема стабильности фермы в таких условиях. Проблемы, с которыми программисты сталкиваются во время разработки, в базовом наборе правил SPCop адресованы очень слабо.
Поэтому мы решили создать набор правил для SPCop, чтобы облегчить процесс разработки решений и ловить многие проблемы до того, как они проявятся во время тестирования или промышленной эксплуатации. Также создали правила, которые подсказывают best pratices при разработке решений.
Кстати мы это:

Как использовать

1. Поставить SPCop из галереи расширений Visual Studio
image
2. Скачать spcafcontrib.dll и положить в папку C:\Program Files (x86)\SPCOPCE\
3. Запустить анализ в Visual Studio
image
4. Анализируйте результаты и настраивайте правила
image

Заключение

Сайт SPCAF - http://www.spcaf.com/
Ссылка на сайт проекта - http://spcafcontrib.codeplex.com/
Презентация - http://www.slideshare.net/gandjustas/sharepoint-code-quality
Ставьте, используйте, оставляйте feedback на сайте проекта.


Поиск в приложениях SharePoint. Часть 2.

Untitled

Первая часть этой серии была написана примерно полтора года назад, после этого появился SharePoint 2013, в котором добавили очень много возможностей для использовании поиска в решениях. Но недавний опрос в сообществе (https://www.facebook.com/groups/sharepointrussian/permalink/514677285314072/?stream_ref=2) показал, что наиболее популярной версией до сих пор является SharePoint 2010.

В первой части я рассказывал как использовать стандартные веб-части поиска в SharePoint 2010, теперь расскажу как с помощью небольшого объема кода получить максимальное мощное решение для создания порталов.

DataFormWebPart

Стандартная веб-часть SharePoint позволяет использовать различные источники данных и формировать разметку с помощью XSL. Источник данных описывается с помою класса наследника System.Web.UI.DataSourceControl. В разметке страницы или .webpart файле можно указать какой DataSource использовать в веб-части.

SearchDataource

Для начала создадим DataSource, который возвращает результаты поискового запроса. На MSDN есть инструкция по созданию класса DataSource - http://msdn.microsoft.com/RU-RU/library/92e191zc(v=vs.90)

public class SearchDataSource: DataSourceControl
{
    protected override DataSourceView GetView(string viewName)
    {
        return new SearchDataSourceView(this);
    }


                
            


Восприятие SharePoint

Пост-перевод http://veroniquepalmer.com/2014/01/16/your-sharepoint-perception/

Не правда ли, что мы склонны видеть мир через через призму нашего опыта, но не так, как на самом деле. Возьмите SharePoint например ...

  • Если вы пришли из области автоматизации работы, то SharePoint всего лишь движок workflow.
  • Если вы пришли из области работы с документами, то SharePoint всего лишь хранилище документов с метаданными.
  • Если вы пришли из области веб-дизайна, то SharePoint обязательно надо брендить.
  • Если вы пришли из области разработки, то SharePoint обязательно требует кастомизации.
  • Если вы пришли из области обработки данных, то SharePoint всего лишь панели монтиторинга.
  • Если вы пришли из области обучения, то SharePoint можно использовать только после обучения.
  • Если вы пришли из области управления, то SharePoint работает только если есть регламенты.
  • Если вы пришли из области бизнес-анализа, то SharePoint требует годы планирования.
  • Если вы пришли из области социальных медиа, то SharePoint можно использовать только с версии 2013.
  • Если вы пришли из области разработки расширений, то SharePoint может работать только вашим самым продаваемым продуктом.

И так можно продолжать очень долго.

Это человеческая природа, думать, что наш путь является единственным Но это не так, это лишь один из способов. Нельзя фокусироваться на одной вещи, так как SharePoint это очень большая платформа и умеет много чего еще.

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

Наша работа требует беспристрастной оценки всех возможностей, понимания всех плюсов и минусов, чтобы создавать более качественные решения для ваших клиентов.

perception



Нелегкая судьба Best Practices

НеНаступи_small

(картинка отсюда)

Именно такое отношение к лучшим практикам встречается чуть менее, чем всегда. Можно подумать что не все знают про эти best practices. Но как только человек делает что-то не так, ему сразу же указывают как делать правильно. И что после этого происходит? НИЧЕГО. Только единицы начинают делать правильно после того как узнают про best practices, остальные продолжают жрать кактус и плакать о плохих менеджерах\вендорах\подрядчиках\клиентах\государстве.

Почему так происходит?

  1. Люди последовательны. Если человек уже что-то делает одним образом, то существует психологический барьер делать по-другому.
  2. Люди избегают потерь. Потому что в "другой путь" уже вложено много сил, и есть психологический барьер отказаться от этих "результатов" и пойти правильным путем.
  3. Люди не хотят быть неправыми. Есть у людей такой психологический механизм, который рационализирует любое нерациональное поведение. Даже если первоначальные действия были просто ошибкой, то человек придумает 100500 причин почему этот путь был самым правильным.

Вывод

Если кто-либо (в том числе Вы) не следуете best practices, то для этого почти никогда нет никаких рациональных причин. Когда следующий раз вы узнаете про лучшие практики в вашей области и подумаете "это мне не подойдет потому что...", остановитесь, и еще раз взгляните на картинку в начале поста.



Сообщество по SharePoint на facebook

Исторически так сложилось, что для общения всех заинтересованных людей по SharePoint не было единой площадки в Интернет.

Были и есть форумы на GotDotNet.ru (сейчас лежит) и MSDN\Technet, но оба сфокусированы на вопрос-ответ и населены новичками, которые пытаются сделать что-то нехорошее.

Поэтому я решил создать группу на facebook, чтобы собрать в одном месте всех экспертов и тех, кто хочет получить новую информацию или обменяться мнениями.

Присоединяйтесь к https://www.facebook.com/groups/sharepointrussian/



Улучшаем экспорт в Excel для SharePoint

Стандартная возможность экспорта в Excel в SharePoint работает довольно необычным образом. При нажатии на кнопку экспорта SharePoint отдает файл запроса в специальном формате, который открывается Excel и  уже сам Excel затягивает данные.

Преимущество такого подхода в том, что данные в Excel можно обновить, так как есть соединение. Но недостатков больше:

  1. Нужен установленный Excel на компьютер, чтобы получить данные.
  2. В полученном документе для названий колонок используется InternalName полей.
  3. В полученном документе используется “сырой” формат данных, что далеко не всегда подходит.

С помощью небольшого объема кода можно подменить стандартную функцию экспорта на свою так, что пользователи ничего не заметят.

Подмена кнопок экспорта

Чтобы заменить существующий элемент в Ribbon надо добавить новый CommandUIDefinition с параметром Location равным Id существующего элемента. Все стандартные элементы находятся в файле C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\GLOBAL\XML\CMDUI.XML для SharePoint 2010 (или 15 для SharePoint 2013).

Для того, чтобы подменить кнопки экспорта в Excel надо найти кнопки с Id равными Ribbon.List.Actions.ExportToSpreadsheet и Ribbon.Library.Actions.ExportToSpreadsheet и полностью скопировать в свой проект. В качестве Location для новых элементов надо указать эти Id.

<CommandUIDefinitions>
  <CommandUIDefinition
    Location="Ribbon.Library.Actions.ExportToSpreadsheet">
    <Button Id="Ribbon.Library.Actions.ExportToSpreadsheet-Replacement"
      Sequence="40"
      Command="ExportToSpreadsheet-Replacement"
      Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png" Image16by16Top="-152" Image16by16Left="-32"
      Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png" Image32by32Top="-352" Image32by32Left="0"
      LabelText="$Resources:core,cui_ButExportToSpreadsheet;"
      ToolTipTitle="$Resources:core,cui_ButExportToSpreadsheet;"
      ToolTipDescription="$Resources:core,cui_STT_ButExportListToSpreadsheet;"
      TemplateAlias="o2"
        />
  </CommandUIDefinition>
  <CommandUIDefinition
    Location="Ribbon.List.Actions.ExportToSpreadsheet">
    <Button Id="Ribbon.List.Actions.ExportToSpreadsheet-Replacement"
      Sequence="40"
      Command="ExportToSpreadsheet-Replacement"
      Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png" Image16by16Top="-152" Image16by16Left="-32"
      Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png" Image32by32Top="-352" Image32by32Left="0"
      LabelText="$Resources:core,cui_ButExportToSpreadsheet;"
      ToolTipTitle="$Resources:core,cui_ButExportToSpreadsheet;"
      ToolTipDescription="$Resources:core,cui_STT_ButExportListToSpreadsheet;"
      TemplateAlias="o1"
        />
  </CommandUIDefinition>
</CommandUIDefinitions>

Есть еще отдельная кнопка для календаря с Id="Ribbon.Calendar.Calendar.Actions.ExportToSpreadsheet", с ней можно сделать тоже самое.

Создание контрола

Кнопка должна вызывать некоторый серверный код. Чтобы поведение было аналогично стандартной кнопке лучше всего сделать DelegateControl, который будет размещаться на каждой странице. Для этого есть контейнер с Id="AdditionalPageHead"

<Control 
  Id="AdditionalPageHead"
  Sequence="1000"
  ControlAssembly="$SharePoint.Project.AssemblyFullName$" 
  ControlClass="$SharePoint.Type.7fd7c6f0-4eda-48ce-ac8f-aa9f9d2666ac.FullName$"/>

Кастомная кнопка будет вызывать PostBack, обрабатываемый нашим контролом. Кнопка может быть нажата на странице представления списка, тогда не надо передавать дополнительных параметров на сервер. Представления списков могут быть добавлены на обычные страницы как веб-части, тогда нужно передать Id списка и представления на сервер.

Увы, получение Id представления, в котором была нажата кнопка – нетривиальная задача. Поэтому я ограничусь только передачей Id списка.

<CommandUIHandlers>
  <CommandUIHandler
    Command="ExportToSpreadsheet-Replacement"
    CommandAction="javascript:(function(){var x=SP.ListOperation.Selection.getSelectedList(); if (x) {__doPostBack('ExportToSpreadsheet-Replacement', x);}})();" />
</CommandUIHandlers>

Далее на сервере нужно проверить нажата ли кнопка на странице представления списка или на обычной странице:

protected override void OnLoad(EventArgs e) { 
    if (this.Page.Request["__EVENTTARGET"] == "ExportToSpreadsheet-Replacement") 
    {
        var spContext  = SPContext.Current;
        SPList list;
        SPView view;


                
            


Как обычно делают корпоративный портал на SharePoint

Недавно на facebook был опубликован (не мной) просто эпичный пост про корпоративный портал на SharePoint. Поиска по постам на facebook нет, поэтому приведу содержание здесь:

...а в конце декабря мы решили-таки натянуть новый дизайн на наш корпоративный портал. В итоге, отработав все предпоследние выхи года, получив, таким образом, поистине бесконечную 12-дневную рабочую неделю, дизайн мы-таки натянули и даже выловили все крупные и критичные баги, а не критичные оставили на новый год.

В итоге, в крайнюю пятницу старого года, взяв 30е и 31е декабря в счёт отработанных выхов, иду в бар, пью пиво и вообще всячески начинаю радоваться наступившим наконец каникулам. Но радость моя длилась ровно 2 дня, пока не закончились выходные.

В понедельник меня будит звонок руководителя, который сообщает, что портал не работает. При чем весь и полностью. До этого у нас были проблемы с главной страницей, но мы их успешно решили. А тут умерло вообще все. Ни один сайт не открывается. Исследования показали, что серваки просто не справляются с нагрузкой: очередь в IIS как при СССР за докторской колбасой, а памяти она жрет больше обычного раза в три. Кое-как продравшись в layouts, меняю мастер-страницу на дефолтную и наследую её для всех узлов. Портал моментально взлетает. Почти. Весь, кроме главной страницы. Выяснилось, что на главной странице masterpage жестко прописан в коде. Так как подрядчиков было уже не достать, оставил всё как есть и почти счастливо пошел отмечать новый год.

Сегодня танцы с бубном продолжили уже подрядчики. Код их, деньги уже уплочены, так что пусть свои косяки и исправляют. И что в итоге? А всё очень просто. В masterpage оказалась вшита веб-часть, которая подгружала курсы валют с сайта cbr.ru, но подгружала она не на серверной стороне, а на клиентской без какого-либо кеширования. В итоге, админы cbr получив с одного IP 100 000+ запросов за менее чем рабочий день, банально нас забанили. Веб-часть же начала ругаться на отсутствие аутентификации. А так как написана она была левой пяткой, то ругалась до бесконечности, не позволяя подгрузить о стальной контент страницы. Баг, который может проявиться только при опытной эксплуатации и на тестах его выявить практически нереально.

Автор поста – админ, не программист, но хорошо разбирается в SharePoint. Поэтому оставим технические детали вроде серверной\клиентской стороны для веб части (судя по симптомам загрузка курсов была именно на сервере).

Первоначально все накинулись на подрядчиков с рекомендациями писать try\catch. Но ошибка, вероятнее всего, была вызвана как раз использованием try с пустым catch (без throw) в цикле. Ошибка довольно типичная для среднестатистического разработчика SharePoint. Но самое важное в этой истории как раз то, что не написано и не касается подрядчиков вообще.

Какая необходимость вообще возникла пихать информер курсов валют на все страницы всех сайтов портала? От этого есть реальный value? Даже в финансовых организациях от силы 30% сотрудников будут получать преимущество от такого функционала, но у них, скорее всего, будет специальный софт, где будут и курсы валют и многое другое. А в среднестатистической организации курсы валют на каждой странице не нужны никому, а если вдруг кому-то понадобятся, то они быстрее зайдут на сам cbr.ru.

Коммент на тему откуда вообще появились курсы валют:

Курсы валют все равно есть и в 1С и на всяких яндексах и т.д. Но партия (руководство) сказала надо, значит надо.

Это прекрасно! Полтора года назад у меня уже был пост на тему создания решений, где тоже все свелось к мифическому “руководству”. Значит и подходы, описанные  в моем посте, остаются такими же верными.

Также очевидна проблема с управлением проектом. Это надо быть очень везучим, чтобы накатывать большое обновление за несколько дней до нового года и ничего не сломалось. Но оказывается все еще интереснее:

...но проект должен был быть завершен в августе, а так как все сроки подрядчики просрали их заставили до НГ все закончить.

То есть кто-то посчитал что подрядчики, которые уже зафейлили один срок и работают в режиме аврала, сделают решение, которое не упадет на продакшене? И при этом не было никакого контроля качества? И при этом решили ставить обновление перед новым годом, а потом сразу идти в отпуска, думали что все будет хорошо?

Ну и корень всей этой ситуации:

скажу просто, что данных подрядчиков выбирали по красивой картинке, кто лучше нарисовал, тот и выиграл. Над Business-value никто особо не заморачивался. По большому счёту этот редизайн вообще никому из простых юзеров не нужен был.

Без комментариев...

Резюме

Вот так обычно делают порталы на SharePoint:

  1. Выбирают по красивой картинке (проблема заказчика).
  2. Не работают с требованиями (проблема заказчика).
  3. Полное отсутствие менеджмента проекта на стороне заказчика (понятно чья проблема).
  4. Полное отсутствие контроля качества на стороне заказчика (аналогично) .
  5. Подрядчики не обладают достаточной квалификацией по созданию порталов (по сути единственная проблема подрядчиков).
  6. У заказчика вообще нет стратегии внедрения и развития портала.

При этом все ругаются именно на подрядчиков. Хотя даже с плохими подрядчиками можно делать хорошие проекты, при нормальном менеджменте у заказчика.

Если же нет специалистов у заказчика, то обязательно нужно нанимать консультантов ДО начала проекта. Это позволит сэкономить гораздо больше денег.



Как работает развертывание решений в SharePoint

Развертывание решений SharePoint - это нескончаемый источник ошибок, слухов и легенд. Причина этому простая – процесс деплоймента (и отката) решений практически никак не документирован. Начиная с SharePoint 2010 ситуация усложнилась появлением sandbox solutions и механизмом апгрейда фич.

Общая схема

(взято отсюда)

По пунктам:

  • WSP пакет сначала попадает в конфигурационную базу
  • При развертывании файлы из пакета попадают на компьютеры фермы, это касается фич, сборок и файлов приложения.
  • При активации фич на основе манифеста в контентной базе создаются записи, которые ссылаются на файлы на диске.

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

На практике такая схема работает плохо...

Проблемы

Когда артефакты (файлы, поля, типы контента, списки) создаются таким образом, как описано выше, они называются ghosted (в SharePoint 2007) или uncustomized (с SharePoint 2010).

Проблемы начинаются тогда, когда файлы\поля\типы\списки изменяются. Когда это происходит в базу записывается схема (XML определение) или сам обновленный файл, а связь с файлом на диске теряется. Это состояние называется unghosted или customized. Дальнейшее обновление путем обновления файлов на диске уже перестает работать.

Ситуация усугубляется тем, что деактивация фич не удаляет списки и файлы и не удаляет типы контента и поля, на которые ссылаются списки. Повторная активация фич, при наличии артефактов в контентной базе, работает совершенно непредсказуемо.

Это кстати одна из базовых ошибок дизайна feature framework, из-за которой весь деплоймент стал невероятно сложным. Если бы деактивация фич удаляла все артефакты и при удалении решения фичи деактивировались, то делать решения стало бы гораздо легче. Но в 2007 году об этом не подумали и сделали выбор в пользу сохранения данных, а не контролируемости развертывания.

Можно, конечно, все артефакты создавать с помощью XML, избегая кода, который вызывает кастомизацию. Но далеко не все решения можно делать таким образом. Многие вещи, вроде таксономии, audience targeting и metadata mavigation в XML описать очень сложно. Но самое главное, что кастомизация может быть вызвана пользователем. А если возможность кастомизации заблокировать, то теряется гибкость, которую дает SharePoint.

Еще одна проблема связана со списками и шаблонами (определениями) списков. Если список создан по шаблону и не кастомизирован, но шаблон отсутствует на диске, то появляется множество непонятных ошибок при использовании API и некоторых стандартных функций.

Из-за этих проблем многие полностью отказались от развертывания артефактов с помощью XML определений и начали делать создание артефактов с помощью кода. Этот подход гораздо более многословен и повышает вероятность ошибок, но при этом дает контролируемость процесса при создании, и самое важное, при обновлении артефактов.

SharePoint 2010 и Sandbox

Естественно в Microsoft обо всех этих проблемах знали и в 2010 версии сделали некоторые изменения, которые должны были улучшить ситуацию.

Первое изменение – добавление флагов Overwrite в определениях полей и типов контента. С этим флагом поля и типы при активации фичи записываются в контентную базу, без создания привязки к файлам на диске. Кроме того стала возможна повторная активация фич при наличии артефактов в контентной базе данных. Это частично решает проблему, но только частично, так как проблема со списками, созданными из шаблонов, не решается.

Второе изменение – добавление возможности апгрейда фич. Теперь можно не удалять решение и не переактивировать фичи для получения новой функциональности.

Третье изменение – появление Sandbox решений, которые не используют файлы в файловой системе и создают все артефакты сразу в контентной базе. При этом откат Sandbox решения вызывает деактивацию всех фич, а для FullTrust такого не происходит.

Казалось бы теперь можно сделать то что нужно, используя правильные возможности. Но вышла еще одна промашка – все изменения почти никак не документированы и процесс развертывания стал еще более непредсказуемый и вообще сложилась ситуация когда никто не знает как делать правильно.

В SharePoint 2013 кстати тоже произошли небольшие улучшения, но снова почти не документированные.

Что же делать

Вариант первый – делать все кодом. К сожалению кода получается очень много и писать его очень муторно. Некоторые вещи сделать кодом сложно, некоторые вообще невозможно.

Вариант второй – делать развертывание в XML, не деактивировать фичи (особенно если ведет к потерям данных или к нарушению работоспособности), не откатывать решение, использовать feature upgrade. Это тоже требует написания кода, но в гораздо меньшем объеме.

Кстати использовать активацию фич для поставки функционала пользователю – тоже не лучший вариант. Гораздо лучше:

  1. Создание сайтов по шаблону.
  2. Создание списков по шаблону.
  3. Дополнительными пунктами в меню администрирования (для сайтов, списков, типов контента).
  4. Расширением существующего функционала.

Сам фичи лучше всего делать скрытыми, активировать их автоматически при развертывании решения или скриптом установки.

Если же делаете фичу видимой, то нужно всегда тестировать возможность её многократной активации\деактивации, в том числе на разных сайтах и коллекциях сайтов.

Заключение

Если вы работаете с SharePoint, то вам в любом случае необходимо знать как работает развертывание артефактов. Узнать это можно типовым для SharePoint способом – ковырянием сборок в ILSpy или Reflector. Большую часть из того, что я описал в этом посте я узнал именно из сборки Microsoft.SharePoint.

В следующий раз расскажу как пользоваться работает feature upgrade и как быстро создавать решения в SharePoint.



SPTypeScript Release 1.3

TypeScript неумолимо приближается к релизу, недавно вышла версия 0.9.5.

Вместе с этим мы продолжаем развивать наши определения типов JavaScript Object Model в SharePoint, чтобы вам было комфортно писать клиентский код для решений и приложений SharePoint.

На сайте проекта http://sptypescript.codeplex.com/ опубликован новый релиз, в который вошли:

  • Определения для Chrome Control для apps.
  • Определения для SPClientPeoplePicker для создания кастомных форм с контролом выбора людей.
  • Полные определения типов для пространств имен SP.Publishing и SP.DocumentManagement из файлов sp.publishing.js и sp.documentManagement.js соответственно. Они вам очень пригодятся для ECM\WCM сценариев.
  • Reputation object model – для социальных приложений.
  • Множество примеров и мелкие улучшения существующих определений.

Ссылка на релиз - http://sptypescript.codeplex.com/releases/view/115896

Также последнюю версию определений можно получить с помощью NuGet -http://www.nuget.org/packages/sharepoint.TypeScript.DefinitelyTyped/

Как использовать TypeScript для приложений SharePoint

Для начала установите последнюю версию TypeScript (0.9.5).

Создаете новый App для SharePoint в VisualStudio 2013

image

Теперь самое неприятное – надо поправить .csproj файл, чтобы включить компиляцию TypeScript. Для этого надо:

  • В контекстном меню проекта нажать Unload Project
  • На выгруженном проекте нажать Edit
  • В самом конце, перед закрывающим тегом Project надо добавить одну строчку:

    <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets" />

  • На выгруженном проекте нажать Reload Project
  • Верить что к релизу не придется исполнять эти танцы с бубном...

После этого надо выставить настройки проекта в свойствах проекта
image

Далее переименовываете App.js в _App.js. Удалять не надо, он еще пригодится.

image

Добавляете App.ts файл

image

Добавляете дефинишены для SharePoint и JQuery с помощью NuGet

image

Копируете содержимое _App.js в App.ts и удаляете _App.js и сразу получаете типизацию в .ts файле. Можно также сделать небольшой рефакторинг в стандартном шаблоне, чтобы максимально использовать типизацию:

image

Последний штрих – скомпилировать проект и добавить сгенерированные App.js и App.js.map в решение.

image

Теперь можно запускать приложение и будет работать отладка в .ts файле

image

Планы на будущее

Сейчас дефинишенами покрыто почти все API для которого можно хоть как-то найти документацию. К релизу TypeScript 1.0 мы выпустим версию SPTypeScript 1.5 (или 2.0). Если есть какой-то API SharePoint, для которого вы хотите видеть дефинишены в нашем проекте, пишите на CodePlex в раздел Discussions - http://sptypescript.codeplex.com/discussions.

Будем рады любому фидбеку.



SharePoint Day: 14 декабря, Москва

14 декабря 2013 года состоится встреча встреча Russinan SharePoint User Group (RUSUG) в новом формате. Встреча будет проходить в субботу в офисе Microsoft в Крылатском. Вместо обычных двух докладов будет целых шесть в два потока. Начало в 10.00. Как всегда будет вестись трансляция для тех, кто не сможет приехать.

Внимание. Регистрация обязательна. Зарегистрироваться можно по ссылке http://rusug.timepad.ru/event/95901/. Выбирайте правильный тип регистрации.

Программа мероприятия:

Время / Поток

Поток 1

Поток 2

10:00 - 11:00

Все что вы хотели узнать про Office Web Apps Server 2013, но боялись спросить

Илья Бойко

Yammer для разработчика

Михаил Бондаревский

Перерыв

11:15 - 12:15

Как улучшить качество решений для SharePoint. Пособие для владельцев ферм и разработчиков

Стас Выщепан (это я)

Планирование в Excel + PowerShell = Готовый портал SharePoint 2013

Сергей Слукин

Перерыв

12:30 - 13:30

SharePoint 2013. Поиск в корпоративной среде

Виталий Жуков

Новая прадигма брендинга в SharePoint 2013

Александр Романов

Перерыв

13:45 - 14:30

Круглый стол

Страница мероприятия на facebook - https://www.facebook.com/events/183651665162179/

Описания докладов можно найти по ссылке - http://www.gotdotnet.ru/blogs/sharepoint/14107/

Присоединяйтесь все желающие, до встречи в субботу.

PS. Формат субботних встреч по SharePoint (SPSaturday) очень популярен в мире - https://www.google.ru/#q=spsaturday. Надеюсь и у нас приживется.



Безопасность приложений SharePoint 2013

Система разрешений в новой архитектуре приложений в SharePoint 2013 (о которых я писал ранее) до сих пор вызывает много вопросов. Попробую прояснить некоторые из них:

Введение

Когда вы создаете решение код работает под учетной и с правами того пользователя, который этот код запустил. Это сильно повышает безопасность платформы, но усложняет написание кода.

В FullTrust возможно повышение привилегий путем создания объекта SPSite с токеном более привилегированного пользователя (SPUserToken.SystemAccount). Код с повышенными привилегиями может делать всё (вообще всё). Поэтому любое решение или опасно, или почти бесполезно. Еще одна проблема повышения привилегий – невозможно отследить какой пользователь и какие действия вызвали изменения, потому что везде будет один и тот же пользователь даже для разных решений.

App Principals

Для решения проблем обозначенных выше, приложения решили сделать участниками системы безопасности (principal), также как и пользователей. Это означает что у каждого приложения есть свой App Principal, которому назначаются права.

Пользователь сопоставляется со своим principal в процессе аутентификации, то есть при передаче логина\пароля (или токена) от пользователя к SharePoint.

А как же происходит аутентификация приложений, ведь нету логинов и паролей у приложений...

Этот процесс описывает простая схема:

image

Схема не совсем точная, но в общем описывает процесс правильно.

Если не вдаваться в детали, то выполняются такие условия:

  1. Если пользователь аутентифицирован и происходит запрос к AppWeb, то используется App Principal + User Principal (внутренняя аутентификация).
  2. Если пользователь не аутентифицирован, но в запросе указан access token (внешняя аутентификация), то
    • Если в access token указан user identity, то то используется App Principal + User Principal.
    • Если в access token не указан user identity, то то используется App Principal  с App Only-Policy.
  3. Во всех остальных случаях аутентификация для приложения не происходит.

Внутренняя аутентификация

Скриншот манифеста свежесозданного SharePoint-hosted app, обратите внимание на элемент AppPrincipal.

image

Внутренняя аутентификация называется так, потому что все процессы аутентификации приложения происходят внутри SharePoint. Вам для этого не надо ничего писал и\или настраивать (только DNS для AppWeb).

Внутренняя аутентификация используется именно для SharePoint-hosted app и JavaScript кода. В других случаях сложно повторить условия для внутренней аутентификации. Чтобы нельзя было обойти внутреннюю аутентификацию и проверку прав приложения AppWeb создается на уникальном домене. Это позволяет блокировать JavaScipt обращения, используя same origin policy, которая встроена в браузер.

Есть еще возможность размещать клиентский JavaScript внешнем сайте, и он будут обращаться к AppWeb и будет работать аутентификация приложения.

Внешняя аутентификация

Если же поменять тип приложения на Provider-hosted , то можно увидеть такой манифест:

image

В элементе AppPrincipal появилось RemoteWebApplication. ClientId="*" заменяется на идентификатор приложения при отладке или публикации.

access token должен содержать идентификатор приложения, чтобы SharePoint мог привязать AppPrincipal. Для формирования Access token используется oauth или s2s trust. Оба доступны только в серверном коде внешнего приложения и не доступны в клиентском JavaScript.

Основная проблема в том, что нельзя одновременно указать внутреннюю и внешнюю аутентификацию. То есть нормально обращаться к SharePoint сможет или серверный код на внешнем сайте или JavaScript на AppWeb. Учитывая что многие стандартные компоненты SharePoint используют JSOM, то они не будут работать при внешней аутентификации. Это делает AppWeb почти бесполезным для Provider-hosted приложений.

OAuth

OAuth это протокол (правильнее сказать фреймворк), который описывает протоколы и сценарии аутентификации приложений в вебе. В Office 365 используется схема с тремя действующими лицами:

  • Приложение
  • Access Control Service (ACS)
  • SharePoint

SharePoint и приложение доверяют ACS, SharePoint не доверяет приложению напрямую (и правильно делает :) ).

Процесс аутентификации выглядит так:

  1. Пользователь нажимает на плитку приложения.
  2. SharePoint запрашивает у ACS так называемый context token по ClientId приложения и отдает context token клиенту (браузеру). Context token подписан с помощью ClientSecret, который известен ACS и приложению.
  3. Браузер делает POST запрос на адрес приложения и передает context token.
  4. Приложение проверяет context token с помощью ClientSecret и извлекает refresh token.
  5. Далее по refresh token приложение может получить access token от ACS и обращаться с ним к SharePoint.

Описание на MSDN: http://msdn.microsoft.com/en-us/library/office/fp142382.aspx

Параметры ClientId и ClientSecret вы получаете при регистрации в Office Store или при добавлении нового app principal на странице /_layouts/15/appregnew.aspx.

Важные моменты:

  •  Context token передается приложению POST запросом. При переходе н другую страницу в приложении context token не сохранится. Само приложение должно это делать. В Visual Studio 2013 включили класс SharePointContext, который управляет сохранением токенов в сессии.
  • Из-за использования POST нельзя реализовать OAuth на клиентском JavaScript. Даже не пытайтесь.
  • SharePoint и ACS напрямую не обращается к вашему приложению, кроме случаев использования Remote Event Receiver или Workflow. Поэтому SharePoint абсолютно все равно где и на чем работает ваше приложение. Это например позволяет отлаживать облачные приложения на локальной машине.

OAuth полагается на SSL, так как все токены передаются незащищенными от перехвата. Любое приложение SharePoint для Office 365 должно иметь SSL сертификат.

Как я писал ранее, в onprem по-умолчанию не работает OAuth и используется его расширение S2STrust. Можно интегрировать onprem ферму с тенантом office365, тогда появится возможность устанавливать provider-hosted приложения из маркета. Подробнее тут: http://msdn.microsoft.com/en-us/library/office/dn155905.aspx

S2S Trust

В onprem варианте вместо “трехногого” OAuth используется “двуногий” вариант, называемый Server-to-Server Trust. Суть в том что SharePoint доверяет серверу приложения. Для установления факта доверия в SharePoint должен быть добавлен Trusted Token Issuer, а это требует сертификата. Приложение этим сертификатом подписывает запросы на получение access token пользователя.

В “двуногой” схеме никаких context token и refresh token не используется. Приложение должно само аутентифицировать пользователя и передавать данные о текущем пользователе в SharePont. Да, это позволяет приложению притворяться любым пользователем.

Такие приложения называются приложением с высоким доверием (High trust), в отличие от full trust права приложения все-таки ограничиваются.

Подробнее тут: http://msdn.microsoft.com/en-us/library/office/fp179901.aspx

Права приложений

Независимо от того, какой вид аутентификации приложения используется,  приложению назначаются разрешения. Права приложения отличаются от прав пользователей:

  • Требуемые права задаются в манифесте.
  • Права приложению даются при установке по принципу “все или ничего”.
  • Права приложений не используют иерархию объектов SharePoint.

Вот так выглядит запрос прав манифесте, указываются области и требуемые права:

image

Полный список возможных разрешений: http://msdn.microsoft.com/en-us/library/office/fp142383.aspx

Для вычисления эффективных разрешений права пользователя и права приложения пересекаются. Porvider-hosted app может также получить app-only access token, если в манифесте приложения было указано app-only policy.

image

Надо учитывать что все это работает только для CSOM и REST вызовов. Обычные (устаревшие) веб-сервисы не поддерживают аутентификацию с помощью access token.

Права – основной источник проблем для приложений. Если вы дадите приложению недостаточно прав, то ошибки буду очень непонятными. Иногда сочетание прав для некоторой операции крайне неочевидно, например:

  • Публикация в социальную ленту требует Social Write, Tenant Write, User Profiles Read, если не дадите одно из них вам скажут “Social list not found” или что-то в этом роде.
  • Добавление типов контента на подсайт требует sitecollection read, хотя если вы будете тестировать приложение на корневом сайте, то прав web manage может хватить.

Есть еще возможность запрашивать права “на лету”, но это тема для отдельной статьи. Пока можете прочитать описание на MSDN: http://msdn.microsoft.com/en-us/library/office/jj687470.aspx

Заключение

Большая часть сложностей аутентификации приложений скрыто от глаз программистов, с помощью внутренних механизмов SharePoint и классов хелперов SharePointContext и TokenHelper. Тем не менее надо хорошо понимать внутренние механизмы, особенно разграничения доступа, чтобы успешно создавать приложения.

С появлением модели apps нагрузка на SharePoint разработчиков сильно возросла, надо изучать много новых технологий и подходов, чтобы эффективно применять возможности платформы.

Изучайте, развивайтесь.



SharePoint Solutions vs Apps

Если вы еще не в курсе что такое apps (приложения), то прочтите предыдущий пост.

На этот рас попробуем разобраться когда надо использовать приложения, а когда стоит делать решения.

Приложения и решения не пересекаются вообще. Для приложений важна изоляция, чтобы приложение не повиляло на ферму и не делало то, чего делать нельзя. Для решений важна интеграция с платформой. Решения могут использовать возможности SharePoint, дополнять и улучшать их.

Microsoft предлагает всем делать приложения, в соответствии с cloud-first политикой. Считается что если сделать приложение, то оно заработает в Office 365 и onprem. Но именно в этом заключается первое заблуждение относительно приложений.

Первое заблуждение

Люди думают что onprem приложения также хорошо работают, как в облаке. На самом деле приложения, сделанные для Office 365 сложно использовать onprem.

Во-первых provider-hosted app просто так не заработают onprem, потому что onprem не работает OAuth. Можно настроить интеграцию onprem с Office 365, но это порядка на два сложнее и затратнее, чем сделать приложение.

Во-вторых можно настроить Server-to-Server Trust (S2S), но для такого приложения потребуется изменение исходного кода, деплой во внутренней сети, powershell скрипт для установки, который требует farm admin привилегий.

В-третьих – поддержка apps в onpremise варианте требует тщательной настройки  - приложения службы, DNS, сертификаты. Особенно часто возникают проблемы если надо выставить ферму с apps в интернет.

Единственный тип приложений, которые можно поставить из маркета, без дополнительных телодвижений – SharePoint-hosted. Но и тут есть проблемы...

Второе заблуждение

Люди считают что SharePoint-hosted app удобно использовать чтобы задействовать возможности SharePoint. На самом это возможно в очень ограниченных сценариях.

Напомню что SharePoint-hosted app – это артефакты SharePoint и JavaScript, размещаемые на отдельном сайте (AppWeb). Подробнее тут - http://www.instantquick.com/index.php/sharepoint-2013-app-web-versus-host-web-redux?c=elumenotion-blog-archive/sharepoint-2013-and-office-365-apps.

Проблемы:

Третье заблуждение

Люди считают что авторизация приложений (разрешения) поможет сделать эти приложения более безопасными. На самом деле разрешения зачастую работают против разработчиков и не способствуют повышению безопасности.

Во-первых для некоторых действий требуется слишком много разрешений. Например запись в социальную ленту требует прав записи в весь Тенант (в Office365) или во всю ферму (в onprem).  Такой высокий уровень разрешений позволяет делать приложению что угодно с вашими данными.

Во-вторых, чтобы установить приложение, пользователь его устанавливающий должен обладать правами, которое требует приложение. Например поставить приложение, требующее прав на тенант (даже только чтение), сможет только админ фермы.

В-третьих в маркет не принимают приложения, требующие full control. То есть серьезное приложение, использующее потенциал SharePoint, поставить из маркета невозможно.

Выводы

  1. SharePoint-hosted приложения подходят только для небольшого изолированного функционала. Например информеров погоды\пробок и (не дай бог) дней рождения.
  2. Provider-hosted в onprem имеет смысл только для интеграции существующего приложения в SharePoint. Создавать новое слишком накладно.
  3. В office 365 имеет смысл делать provider-hosted (с хостингом в Auzre Websites). Но мало что удастся получить приложению от SharePoint. Поэтому скорее будет вариант построить веб-приложение, а потом интегрировать с SharePoint. Примерно так работает новый LightSwitch.

Вкратце приложения имеет смысл делать или для чего-то простого, или для интеграции отдельных веб-приложений в SharePoint. А для всего остального...

Используйте Sandboxed Solution

Если вы начали возмущаться, говорить что Microsoft запретил Sandbox, то будете правы, почти. Microsoft запретил серверный код в Sandboxed решениях. И то “запретил” – громко сказано, сейчас он работает как в облаке, так и onprem.

Но вы можете в вашем решении разворачивать JavaScript код, типы контента, списки, страницы, шаблоны сайтов, workflow (в 2013 они декларативные), схему поиска и прочие радости. При этом также сохраняя стабильность фермы, даже если вы запускаете серверный код. Хотя потребность в серверном коде в SharePoint 2013 гораздо меньше.

Все новые возможности SharePoint 2013 (CSOM\REST, Client-Side Rendering) доступны для решений, также как для приложений. При этом для установки достаточно быть sitecollection администратором. Пока еще работает серверный код в Sandbox, вы можете легко делать Event Receiver.

В Sandbox решении вы легко можете повторить архитектуру приложений, предоставляя пользователям не набор фич, а шаблон сайта, с преднастроенным набором фич.

Когда возможностей sandbox не хватит для реализации функционала вы можете сделать FullTrust решение, которые выставляет User Code Proxy и веб-части, а ваше Sandbox решение их использует. А в Office365, в случае нехватки возможностей Sandbox, можно в iframe показывать внешний сайт и делать Remote Event Receivers.

Заключение

По странному стечению обстоятельств новые возможности SharePoint вдохнули жизнь в концепцию, которую Microsoft пытался похоронить. Sandboxed решения свободны от недостатков SharePoint-hosted приложений, при этом гораздо проще, чем provider-hosted. Именно с них стоит начинать разработку для SharePoint, кроме самых простых случаев.

Кстати маркет можно использовать для привлечения клиентов, сделав прототип\демо вашего приложения в SharePoint-hosted варианте, и предлагая установить sandboxed ршение уже вне маркета.



SharePoint Apps Intro

С момента релиза SharePoint 2013 прошел ровно год. Я специально не писал ничего про Apps, собирал информацию и анализировал опыт.

Что такое Apps

Краткий дисклеймер для тех, кто не в курсе что такое Apps. Идея apps заключается в том, что пользователи смогут самостоятельно устанавливать приложения для SharePoint из Market или внутреннего каталога компании. Примерно также, как это происходит на мобильных устройствах. Но, в отличии от мобильных устройств, любой посторонний код для SharePoint очень опасен. Поэтому нужно этот код максимально изолировать, ограничить в правах и жестко контролировать.

Кажется мы то уже слышали в 2010 году, и тогда это были Sandbox Solutions? Именно! Мотивация такая же, как и раньше – увеличить стабильность фермы и дать больше возможности устанавливать решения пользователям.

Но Microsoft решил пойти шире и сказал что apps вообще не должны работать на серверах SharePoint. Это может быть JavaScript в браузере, или внешний веб-сервис, общающийся с SharePoint с помощью клиентской объектной модели.

Так как код становится внешним, по отношению к SharePoint, то там можно использовать любые языки и библиотеки. Angular или Backbone на клиенте, ASP.NET MVC+EF или даже PHP+MySQL на сервере.

Архитектура Apps

Здесь и далее я буду называть apps - приложениями, а solutionsрешениями.

Приложения ставятся на сайт (SPWeb) из того же интерфейса, из кодоторого создаются списки. Более того, теперь списки тоже называются приложениями, но это не более чем маркетинговый ход.

Технически приложения для SharePoint представляют манифест, который описывает как можно обратиться к App. Способов на самом деле немного:

  • Переход по ссылке на сайт приложения, это обязательно для любого приложения.
  • Отображение в iframe на странице SharePoint, примерно как веб-часть в решении.
  • Переход по ссылке или отображение в iframe в виде диалога из Ribbon или меню, примерно как custom action в решении.

Еще можно привязать внешний event receiver, но это уже нужно делать в коде приложения.

А теперь главный вопрос: где же будет работать приложение?

Тут два варианта:

  • Внешний, по отношению к SharePoint, веб-сервер. Его разработчик должен самостоятельно развернуть, настроить SSL, обеспечить доступность, изоляцию между экземплярами приложений, и прочие радости. Это называется Provider-hosted app. Есть еще вариант автоматического развертывания сайта в Azure из пакета приложения (AutoHosted), но он, спустя год после релиза, толком не работает в Office 365, а onprem скорее всего никогда не будет.
  • Подсайт в SharePoint. Для экземпляра приложения может быть создан отдельный сайт (appweb). На сайт можно разворачивать обычные артефакты SharePoint – страницы, файлы, списки, workflows. Серверный код нельзя деплоить, поэтому доступен только код на JavaScript. AppWeb автоматически удаляется при удалении приложения. Это называется SharePoint-hosted.

Эти два варианта не взаимоисключающие. Вы можете иметь отдельный сервер, где будет работать код на любимом вами языке, при этом приложение будет создавать AppWeb и писать данные туда. Или наоборот, код у вас будет на JavaScript в AppWeb и будет обращаться к веб-сервисам на внешнем сайте.

Маркет и монетизация приложений

Главная завлекаловка для разработчиков – возможность монетизировать приложения. Приложение может быть плантым и иметь разные варианты лицензирования. Платные приложения можно распространять только через маркет, при этом приложения проверяются людьми до попадания в маркет и требуется соблюдение правил (правила).

Маркет очень удобен для пользователей, они могут сами находить и ставить приложения. Не требуется качать файлы, запускать скрипты и делать другие непонятные вещи.

Что может делать приложение

Потенциально почти все. Клиентская объектная модель покрывает очень много возможностей – работа с артефактами SharePoint (сайтами, списками, элементами), поиск, таксономия, профили пользователей, публикация, социальные возможности, BCS и даже Project Server.

При этом для приложений назначаются разрешения, которые запрашиваются при установке. Для вычисления эффективных разрешений права пользователя и разрешения приложения пересекаются. Если приложение имеет доступ на запись, а пользователь может только читать, то записать что-либо не получится.

Еще есть app-only policy, когда права пользователя не учитываются, учитываются только разрешения приложения. Это как повышение привилегий, которого так не хватало в Sandbox. Но, увы, не работает в JavaScript коде.

Стоит ли использовать apps?

Спустя год вполне можно оценить насколько apps получили распространение, достаточно заглянть в маркет: http://office.microsoft.com/en-us/store/results.aspx?avg=osu150. Приложений не просто мало, а очень мало. Немалая часть из них – не живые. Также можно найти аналитику по использованию приложений -  http://www.instantquick.com/index.php/one-month-since-release-observations-lessons-learned-and-future-plans.

Среди моих знакомых мало кто пишет apps, несмотря на то что половина новых проектов стартует на SharePoint 2013.

Есть мнение что apps вообще не приносят ничего полезного для разработчиков: http://blog.furuknap.net/sharepoint-2013-app-model-solves-non-problems-only.

Все это составляет грустную картину про приложения. В следующий раз постараюсь проанализировать недостатки apps и дать развернутый ответ для чего стоит использовать приложения и решения SharePoint...



Материалы со встречи RuSUG 17.10.2013

Мой доклад про TypeScript  в SharePoint



Доклад Виталия Жукова про поиск:



Спасибо всем, кто пришел.



Встреча RuSUG 17-го октября. Наконец-то...

Мы долго ждали и верили и наконец-то... Встреча Russian SharePoint User Group сотоится 17-го котября 2013 года в Microsoft Technology Center на Белорусской в 19:00.

На встрече будут два доклада: мой про TypeScript и применение его в разработке для SharePoint, доклад Виталия Жукова (http://blog.vitalyzhukov.ru/) про Поиск в SharePoint 2013.

Ссылка на эвент на фейсбуке https://www.facebook.com/events/220294124804312

Регистрация обязательна (иначе вас в Microsoft Technology Center не пустят): http://rusug.timepad.ru/event/85241/



Развертывание полей таксономии в SharePoint

Поля таксономии, также известные как поля управляемых метаданных (managed metadata), появились в SharePoint 2010. Метаданные позволяют создавать иерархии терминов, которые можно использовать как справочные значения (c typeahead в UI) и, начиная с SharePoint 2013, для навигации.

Метаданные поддерживают множество языков, синонимы и дополнительные свойства. Можно организовать навигацию по метаданным в библиотеке или фильтрацию по поддереву в поиске SharePoint.

И все было бы прекрасно, но развернуть в составе WSP пакета поле метаданных в списке – очень нетривиальная задача. Можно конечно сделать с помощью кода, некоторые даже очень любят этот подход, но в большом масштабе будет много копипасты и статический анализ делать гораздо сложнее.

Если деплоить с помощью CAML, то возникает две проблемы, но об этом по порядку

Проблема первая – схема поля

Если вы погуглите, то найдете минимум четыре статьи как деплоить таксономические поля:

Все рецепты приведут к неверному результату. Ближе всех к правде оказался последний пост, но и в нем есть проблемы.

Ни в одном посте не указано как поле попадает в список. А именно от этого зависит как поле будет работать. В прошлом посте я писал, что методы полей срабатывают, только если используется ContenTypeRef в схеме List Definition. Эти методы выполняют много работы – добавляют поля в список, привязывают event receiver_ы для синхронизации значений полей таксономии и catchall поля.

Итак правильная схема таксономического поля:

  <Field
       ID="{defbf0ed-377a-4e62-a980-0493ac0ef42e}"
       Name="TaxonomyColumn"
       DisplayName="Taxonomy Column"
       Type="TaxonomyFieldType"
       Required="FALSE"
       Group="Custom Site Columns"
       DisplaceOnUpgrade="TRUE" 
       Overwrite="TRUE"
  >
  </Field>


                
            


3 правила создания списков SharePoint

Как ни странно, но на просторах интернета крайне мало информации как правильно делать списки и библиотеки SharePoint. В книгах об этом тоже редко пишут. Горькая правда заключается в том, что подавляющее большинство приложений содержит ошибки, связанные с развертыванием списков в SharePoint.

Чтобы устранить львиную долю этих ошибок, надо придерживаться следующих правил:

ContentType

Если вы хотите создать список, то не надо лезть в меню Add –> New Item –> List.  Для начала создайте поля для списка и тип контента. Даже если вы думаете, что тип контента будет ровно в одном списке, то все равно создавайте тип контента.

Тип контента вместе с полями деплойте в фиче уровня Site, желательно скрытой, чтобы никто не смог просто так отключить и поломать решение.

В этой же фиче необходимо выполнить все привязки Workflow, различных Policy и форм.

Важно чтобы после активации фичи тип контента был готов к использованию.

ContentTypeBinding

Элемент ContentTypeBinding позволяет привязать тип контента к экземпляру списка. При этом нет необходимости создавать List Definition. Достаточно создать список из одного из стандартных шаблонов, а потом сделать привязку.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ListInstance Title="List1"
                OnQuickLaunch="TRUE"
                TemplateType="100"
                FeatureId="00bfea71-de22-43b2-a848-c05709900100"
                Url="Lists/List1"
                Description="My List Instance">
  </ListInstance>
  <ContentTypeBinding 
      ContentTypeId="0x0100EDFEDEA571A241FD80430F4D48A91346" 
      ListUrl="Lists/List1"/>
</Elements>


                
            


Обновление SharePoint app на TypeScript

В марте я писал про то, как разрабатывать приложения для SharePoint c помощью TypeScript. С тех пор прошло почти полгода, появились новые версии компилятора TypeScript (не совместимые со старыми) и улучшились описания типов для SharePoint (http://sptypescript.codeplex.com). Настало время обновить пример.

Пример приложения

Приложение позволяет фиксировать часы на рабочем месте.

image

Приложение ведет список всех временных интервалов, зафиксированных нажатием кнопок check-in\check-out. Пользователю отображается сумма всех его часов.

Также есть app part с тем же функционалом, но доступный для размещения на любой странице сайта.

Скачать можно по ссылке - TimeTrackerApp v0.9

Подготовка

Для начала необходимо:

Для того чтобы при сборке проекта выполнялась компиляция  TypeScript необходимо добавить в .csproj файл следующие элементы:

<PropertyGroup>
    <TypeScriptTarget>ES3</TypeScriptTarget>
    <TypeScriptIncludeComments>true</TypeScriptIncludeComments>
    <TypeScriptSourceMap>true</TypeScriptSourceMap>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets" />

Библиотеки и определения

Прошлый раз я использовал библиотеки jQuery и knockoutjs с плагинами. В этот раз решил обойтись стандартными средствами SharePoint и небольшим хелпером из проекта sptypescript.

Чтобы все заработало необходимо добавить NuGet пакет sharepoint.TypeScript.DefinitelyTyped (http://www.nuget.org/packages/sharepoint.TypeScript.DefinitelyTyped/). Далее необходимо скопировать файл typescripttemplates.ts в проект, при необходимости поправить ссылку на sharepoint.d.ts.

Представление списка

Прошлый раз интерфейс был сделан на knockoutjs с асинхронной загрузкой данных. Это вызывало заметный лаг между отображением страницы и появлением интерфейса. Такое поведение очень сильно не нравилось и хотелось сделать лучше.

В новой версии интерфейс сделан на основе представления списка. Представление генерирует данные прямо в разметку страницы, и не требуется асинхронная загрузка. Кроме того, представление формирует разметку до рисования страницы. Для пользователя все выглядит, как-будто рисование происходит на сервере.

Для создания представления я воспользовался инструментами visual studio, но запрос пришлось вручную написать (незначимые детали убрал):

<View BaseViewID="2" Hidden="TRUE" >
  <ViewFields>
    <FieldRef Name="DurationInHours" />
    <FieldRef Name="ID" />
  </ViewFields>
  <Query>
    <Where>
      <Eq>
        <FieldRef Name="Author"/>
        <Value Type="Integer">
          <UserID/>
        </Value>
      </Eq>
    </Where>
  </Query> 
  <JSLink>~site/scripts/typescripttemplates.js|~site/scripts/view.js</JSLink>
</View>


                
            


Обновление SPTypeScript

Вчера была опубликовано обновление для SharePoint TypeScript Definitions. Новую версию определений можно получить через NuGet:

http://www.nuget.org/packages/sharepoint.TypeScript.DefinitelyTyped/

Или командой в Package Manager

PM> Install-Package sharepoint.TypeScript.DefinitelyTyped

Что нового

Анимация

В SharePoint 2013 добавили анимацию и, как всегда забыли, выложить документацию по этому делу. Я раскопал как работает анимация. К сожалению возможности библиотеки очень ограничены. Анимация работает для следующих атрибутов элементов:

  • Позиция (x,y)
  • Размеры (ширина, высота)
  • Прозрачность

Есть два способа вызвать анимацию.

Простой:

SPAnimationUtility.BasicAnimator.FadeOut(element); 
SPAnimationUtility.BasicAnimator.FadeIn(element);
SPAnimationUtility.BasicAnimator.Resize(element, width, height);
SPAnimationUtility.BasicAnimator.Move(element, x, y);

И чуть более сложный:

var state = new SPAnimation.State();
state.SetAttribute(SPAnimation.Attribute.Opacity, 0.2);
var animation = new SPAnimation.Object(
                        SPAnimation.ID.Basic_Opacity, 
                        500,  /*duration*/
                        element, 
                        state);


                
            


Многоликий SharePoint

Я часто консультирую людей по поводу SharePoint, и каждый раз я слышу примерно одно и то же: “мы планируем\разрабатываем\внедряем\используем\хотим_выкинуть портал на SharePoint”. Такое ощущение, что единственное для чего предназначен SharePoint – делать порталы. Как битрикс или, не дай бог, друпал. Ситуацию еще подогревают HRы, которые хотят “интранеты” (имея ввиду ровно тоже, что и порталы).

Если же попадается грамотный заказчик,который понимает проблемы за пределами фразы “корпоративный портал”, то подрядчик зачастую пытается впарить свое “портальное решение”. Это “решение” должно закрывать все потребности заказчика одним махом.

Конечно порталы каждый раз разные, но в них очень много общего.

Типовой корпоративный портал на SharePoint

Обычно на портал возлагаются следующие задачи:

  • Портал обязательно должен иметь уникальный дизайн .
  • Портал должен способствовать улучшению коммуникации.
  • Портал должен иметь функцию документооборота.
  • Портал должен быть хранилищем активов для подразделений.
  • Портал должен обеспечивать совместную работу.
  • ..а еще автоматизировать заявки, делать поиск, обязательно нужна мини-crm, голосования, показывать дни рождения и трудовые юбилеи, новости, фотографии, ссылки… ничего не забыл?

Самое странное, что многие цели противоречат друг другу, но это никого не смущает. Например документооборот крайне плохо сочетается с уникальным дизайном. Никому в голову не придет делать уникальный дизайн в Documentum или DocsVision, а в SharePoint это нормально. Хранилище активов требует разграничения доступа в соответствии с организационной структурой, а совместная работа и улучшение коммуникаций, наоборот, требует преодоления рамок организационной структуры. Весь feature soup, который предлагается в качестве полезного функционала, вообще ни как не коррелирует с заявленными целями и присутствует, в основном, “для галочки”. И это еще не самое страшное…

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

Приспособить “портал” под конкретные задачи пользователей оказывается сложно, а без этого adoption становится низкий и вложения не окупаются. Гигантский набор фич на портале используется от силы на 20% и, зачастую, страдает от проблем масштабирования.

Почему так происходит

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

Сам термин корпоративный портал является ментальным шорткатом, который избавляет продавца и покупателя от необходимости выяснения потребностей. Кроме того, для продавца продать "корпоративный портал” – это хороший способ продать проект допиливания портала под конкретные нужды.

Я думаю для многих не секрет, что некоторые вендоры “корпоративных порталов” по факту не имеют портала как продукта (распространяющегося без программистов).

Как сделать правильное решение

Для создания хорошего решения на SharePoint необходимо:

  1. Сосредоточиться на целях
  2. Поставить измеримые KPI
  3. Планировать информационную архитектуру
  4. Создавать самые простые решения

Это, конечно, проще сказать, чем сделать. Нужна хорошая подготовка и богатый опыт,  а также административный вес, чтобы вас слушали. Но это все темы для отдельных постов.

Важно понимать, что у разных целей разные средства решения, архитектура и KPI, возможно противоречащие друг другу.

Примеры решений на SharePoint

Корпоративный поиск

Цель – уменьшить время на поиск информации.
KPI – количество успешных запросов (с кликом на результат) и количество неуспешных (без результатов или без клика на результат). На основании этих величин можно получить экономический эффект и вычислить целевые значения.
Архитектура – искать “везде” обычно плохо работает. Смотрите на поисковую выдачу интернет-поисковиков. Там есть разные типы информации, поиск по разным источникам, продвигаемые результаты,actionable результаты. Адаптируйте к своим источникам и внедряйте.
Решение – стандартный поиск SharePoint 2013. После внедрения поисковая аналитика и “тюнинг” поиска.

Рабочие области команд и проектов

Цель – увеличить эффективность совместной работы.
KPI – количество пересылаемых по электронной почте документов. Взять baseline до запуска системы, уменьшить на 30%-50%-80% по вкусу.
Архитектура – необходимо сделать максимально простой процедуру создания сайтов с библиотекой и списками для совместной работы. Без заявок в ИТ и согласований.
Решение – стандартные сайты команд SharePoint, плоские разрешения, контролируемый жизненный цикл. Обучение пользователей возможностям платформы.

Корпоративный сайт

Цель – сделать единую точку входа для информационных ресурсов компании.
KPI – Количество просмотренных страниц сайта (новостей, событий, фото\видео материалов), количество опубликованных, процент сотрудников, ответивших на опросы. Каждая новость, опубликованная на сайте, должна быть прочитана значительным количеством сотрудников (30% и более), при определенном темпе публикации можно получить довольно точные количественные характеристики.
Архитектура – фиксированные типы информации, малое количество редакторов, простая система разрешений. Участие пользователей – лайки и комментарии, ответы на опросы.
Решение – отдельная коллекция сайтов с режимом публикации, кастомный дизайн, фиксированная структура. Обязательное обучение авторов контента.

Документооборот

Цель – уменьшить время согласования.
KPI – Время согласования документов (по типам). Можно взять baseline с текущей ситуации, уменьшить на 30%-50%-80% по вкусу.
Архитектура – фиксированные маршруты, роли, типы документов. Это очень важный момент. Если в согласовании может принимать участие произвольное количество людей, то считать KPI становится невозможным. Если документы нельзя разделить по типам, то тоже вызывает проблемы расчета KPI.
Решение – Отдельный сайт или коллекция, типы контента, шаблоны, workflow. Предусмотреть вычисление количества дней\часов\минут на согласование. Ну и без обучения, скорее всего, никуда.

Специализированные варианты решений:

  • Enterprise Content Management \ Электронный Архив
  • Автоматизация заявок
  • Базы знаний
  • Системы оценки персонала
  • Системы внутренних вакансий

Попробуйте на досуге продумать конкретные цели и KPI таких систем.

Самое важное – все это разные системы. Нет смысла все валить в одну кучу и называть “корпоративным порталом”, так достичь KPI не получится.



SharePoint Script On Demand

В SharePoint 2013 довольно богатая клиентская библиотека. Ранее я уже писал об аналоге jQuery и об Ajax библиотеках. Одна из важнейших частей для разработки масштабного JavaScipt приложения – загрузчик скриптов. Такое тоже есть в SharePoint.

Почему необходимо управлять загрузкой скриптов

Исторически управление загрузкой скриптов появилось для увеличения быстродействия. Вы наверное знаете, что тег script в теле страницы заставляет браузер останавливать отрисовку страницы. Поэтому скрипты надо загружать как можно позже. Кроме того, в сложных приложениях, все скрипты не нужны на каждой странице, поэтому выгодно загружать их по требованию.

Но важнейшая задача управления загрузкой скриптов – создание полноценной модульности для javascript. Ведь сам язык не предоставляет инструмента описания связей между модулями и гарантий, что зависимости будут загружены до выполнения скрипта.

Обе причины особенно важны в SharePoint. Страницы SharePoint тяжелые, и лучше загружать скрипты как можно позже. Сами же страницы строятся из кучи независимых компонент (созданных разными разработчиками), поэтому модульность скриптов важна как нигде.

В мире веб-разработки фактически стандарт для управляемой загрузки скриптов – библиотека requirejs. Но в ней есть критический недостаток, её придумал не Microsoft, поэтому в SharePoint своя библиотек для загрузки скриптов. Называется она Script On Demand.

Script On Demand

Вся библиотека содержится в классе SP.SOD в файле init.js. Script On Demand спроектирован как неинтрузивная библиотека, в отличие от requirejs, то есть скрипты будут работать и без нее. Это важно в App Parts, которые по сути отдельные страницы в iframe. Там нет смысла откладывать загрузку скриптов.

Документация по SP.SOD есть на MSDN, но она там, мягко говоря, ужасная. В проекте SPTypeScript есть качественные определения типов для SP.SOD, они будут более полезны (SP.Init.d.ts).

Добавление скриптов на страницу

Есть серверный контрол ScriptLink, который позволяет указать в разметке aspx страницы скрипт. По умолчанию скрит будет загружаться сразу же, но асинхронно, то есть не будет блокировать рисование страницы.

У контрола ScriptLink несколько атрибутов:

  • Name – указывает имя скрипта. Если указать только имя файла, то скрипт будет загружаться из _layouts. Поддерживаются url tokens, такие как ~site и ~sitecollection.
  • Localizable – если стоит значение true и указано только имя скрипта, то скрипт будет за загружаться из _layouts/{langId}.
  • LoadAfterUI – если стоит значение true, скрипт будет добавлен в конец страницы (независимо от местоположения контрола ScriptLink) и загрузка начнется после рисования всего интерфейса.
  • OnDemand – если указано значение false или атрибут отсутствует, то генерируется такая разметка:
    <script type="text/javascript">
    // <![CDATA[
    document.write(
        '<script type="text/javascript" src="script.js"></' 
        + 'script>');
    // ]]>
    </script>
    
    
                    
                


Машина разработчика SharePoint в Windows Azure

Ранее я занимался разработкой под SharePoint  на компьютере, стоящим под столом. На нем была развернута виртуальная ферма. Последнее время я всю разработку перенес в облако. Apps отлаживаю на Office 365, серверный код SharePoint создаю и отлаживаю на виртуальной машине в Windows Azure, код храню в Team Foundation Service.

Office 365 и Team Foundation Service – это SaaS, поэтому не вызывает проблем использование и расчет эффективности. А вот виртуалки в Windows Azure (Iaas) вызывают много вопросов.

Почему облака

Доступность

Виртуалка с SharePoint чаще всего нужна когда, когда я не нахожусь дома. С виртуалкой в Azure я могу получит доступ к ней хоть с планшета. Кроме того виртуалки в Azure работают гораздо надежнее, чем дома или, например, в офисе.

Кроме того в Azure виртуальные машины имеют очень толстый канал в интернет, поэтому скачивание дистрибутивов и обновлений происходит за считанные минуты.

Гибкость

Второе преимущество виртуалки в Azure – большая гибкость. В несколько кликов можно добавить или убрать ресурсы (не забываем что за них платить надо), добавить диски или создать новые машины (очень полезно для тестирования).

На домашнем компьютере ресурсы сильно ограничены, а виртуализация только создает иллюзию, не позволяя реально масштабировать инфраструктуру.

Бесплатно

Как владельцу MSDN подписки мне это ничего не стоит. Если же вам все таки придется платить, то расчеты в конце.

Конфигурация

Для того чтобы поднять полноценную среду для разработки вам нужны: контроллер домена с DNS сервером, SQL Server и собственно сам SharePoint. Для целей демонстрации еще понадобится Office Web Apps Server. Причем DC и WebApps должны стоять отдельно, а SQL Server и SharePoint можно совместить. Для разработки это удобно, так как это увеличивает утилизацию ресурсов и не надо по отдельности выключать виртуалки.

А теперь по порядку:

Сеть

Чтобы виртуалки видели друг друга, для начала надо создать виртуальную сеть. Все виртуалки начинают получать адреса по порядку из этой сети. Причем начиная с xx.xx.xx.4 и в порядке включения. В настройках сети также задаются адреса внутренних DNS серверов. Руками править настройки сети в Azure нельзя! Это означает что DNS серверы должны быть включены всегда или должны включаться в определенном порядке, чтобы из IP адреса не менялись.

У меня один DNS сервер на контроллере домена на XS виртуалке и он всегда включен.

Контроллер домена

Тут все просто. Одна XS виртуалка и дополнительный диск для данных домена. Установлены роли AD DS и DNS. Если понадобятся сертификаты, то надо добавить AD CS.

Машина разработчика

Я использую XL виртуалку, на которой стоит SQL Server и SharePoint 2013. На борту 8 ядер (честных, не виртуальных) и 14 ГБ памяти. Для целей разработки этого более чем достаточно.

Но самое главное при работе SharePoint это диски. Быстродействие фермы SharePoint упирается в первую очередь в диски. Когда вы читаете документацию по развертыванию SQl Server и SharePoint там указаны требования к объему дисков, неявно предполагая что все это разные физические диски или как минимум разные LUNы на СХД. Когда разворачивается тестовая ферма или ферма для разработки, то все виртуальные диск попадают на один физический и все дико тормозит.

Диски в Windows Azure это блобы в Azure Storage. Максимальня пропускная способность одного блоба – 60 мегабайт в секунду(http://blogs.msdn.com/b/windowsazure/archive/2012/11/02/windows-azure-s-flat-network-storage-and-2012-scalability-targets.aspx). Внутри виртуальной машины файлы между дисками копируются со скоростью 10 мегабайт в секунду. Но самое главное что для масштабирования IO вы можете добавить столько дисков сколько нужно.

Для SharePoint+SQL Server оптимальной будет такая конфигурация:

  • Диск для данных SQL (можно масштабировать по количеству баз)
  • Диск для логов SQL (можно масштабировать по количеству баз)
  • Диск для tempdb
  • Диск для текстовых логов IIS и SharePoint
  • Диск для индекса поиска

Кроме того можно подключать два виртуальных диска и делать из них striped volume, что должно увеличивать пропускную способность в два раза, но это надо тестировать, я разницы между обычными дисками и striped не увидел при нагрузочном тестировании.

Такая конфигурация работает быстрее, чем на домашнем компьютере.

Тестирование

Для тестов я поднял еще одну машину с Visual Studio и сделал нагрузочный тест для SharePoint. Увы базы SharePoint у меня пустые и кастома почти нет, поэтому результаты тестирования не очень показательны.

Нагрузочный тест открывал главные страницы сайтов разных шаблонов. Нагрузка росла равномерно с 10 виртуальных пользователей до 200.

Результаты нагрузочного теста:

  • 100 requests per senond
  • Все уперлось в процессоры (75% IIS, 25% SQL)
  • Памяти свободной – 1,5 гб (потому что базы пустые)
  • Диски загружены на 15% максимум
  • Примерно на 70 виртуальных пользователях некоторые страницы стали отвечать более 10 секунд
  • IIS ошибок не отдавал

Интересные наблюдения:

  • Для WFE в SharePoint очень важны процессоры, так как страницы “тяжелые” и требуют много ресурсов на рисование.
  • WFE дает нагрузку на диск из-за записи текстовых логов (около 3 мб\сек) в режиме Verbose.
  • Для SQL очень важны диски. Даже в сценарии открытия страниц нагрузка на LOG файлы БД около 1,5 мб\сек.
  • Поиск SharePoint все кеширует в памяти, поэтому для серверов поиска очень важен объем памяти. А также диск, он влияет на скорость индексирования.

Стоимость

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

Расходы:

  • DC – виртуалка XS, работает постоянно – 491 рублей в месяц.
  • SharePoint – виртуалка XL, работает в среднем 172 часа в месяц (8x5) - 4086,72 рублей в месяц.
  • 100гб данных – 231 рублей в месяц.
  • Трафик и тразакции за месяц на разработческой машине стоят меньше 100 рублей.

Итого – чуть меньше 5 тысяч рублей в месяц. С подпиской MSDN дешевле почти в 2 раза.

Для сравнения с настольный компьютер той же мощности обойдется примерно в 50 тысяч рублей и более (чтобы обеспечить такую же скорость и отказоустойчивость хранилища).

Масштабирование

Для команд разработки SharePoint иметь машины на Azure может быть очень выгодно. Сильно повышается мобильность. Можно сэкономить на использовании общего SQL Server на несколько разработчиков, ведь диски масштабируются практически бесплатно.

Заключение

Если вы собираетесь заниматься разработкой и тестированием, то обязательно рассмотрите развертывание инфраструктуры в Azure. Даже если вы – крупный интегратор с кучей внутренних ресурсов, то использование облака может оказаться гораздо удобнее.



Скрытая стоимость решений на SharePoint

Когда сталкиваюсь с разработкой решений на SharePoint часто наблюдаю парадоксальную на первый взгляд картину. С одной стороны заказчик постоянно хочет с экономить на решении. Очень часто исполнитель выбирается исключительно по самой низкой цене. Заказчик часто пытается сократить расходы на анализ потребностей, проектирование и тестирование. С другой стороны к решениями часто предъявляются совершенно неразумные требования, часто противоречащие эффективному использованию этих самых решений. Все это бьет по качеству решения.

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

Из чего складывается скрытая стоимость

Затраты на ожидание

Первый пункт самый банальный. Любая компьютерная система имеет время реакции на действия пользователя. Самое простое – время открытия страницы. Если пользователь открывает 20 страниц в час, то за день выходит 160 страниц. Если вместо двух секунд страница открывается 6 секунд, то за день только в ожидании страниц пользователь проводит 10 минут. Для 100 пользователей это уже значительное время. А время = деньги.

Сюда относится время простоя системы из-за неполадок, обновлений и тому подобных вещей.

Слишком много ручных действий

Казалось бы, в чем проблема нажать кнопку, или вбить значение в поле. Но если это делается много раз  в день, то возникает две проблемы. Первая – время затраченное на эти действия. Вторая – чем больше ручных действий, тем больше вероятность ошибиться.

Поиск информации

Очень часто системы позволяют вводить много информации, тысячи документов, миллионы элементов списков. Но извлечь нужную информацию из системы далеко не всегда возможно и легко. Часто это пытаются решить вводом большого количества метаинформации, но это приводит к проблемам, описанным в предыдущем пункте.

Исследования показывают, что сотрудники, занимающиеся обработкой информации тратят на её поиск от 15% до 35% времени. Источник: http://www.kmworld.com/Articles/Editorial/Features/The-high-cost-of-not-finding-information-9534.aspx.

Обходные пути

Часто бывает так, что решение вроде работает, но иногда падает или дает не тот результат. Ошибка вроде некритичная и есть обходной путь. В таких условиях заказчик обычно принимает решение и подписывает акты, а исполнитель обычно подобные ошибки не правит.

Обходные пути могут отнимать много времени, но часто они настолько входят в привычку, что люди перестают воспринимать обходной путь как проблему.

Обращения в службу поддержки

Когда решение сделано некачественно, службе поддержки приходится гораздо чаще отвечать на вопросы пользователей. Кроме того часто могут требоваться вмешательства администраторов системы для восстановления нормальной работы. Это прямые затраты для службы поддержки и косвенные затраты на ожидание для пользователей.

Доработки

Чем ниже качество системы, тем чаще требуются доработки и тем дороже они стоят. Часто еще возникает проблема что поставщик решения – по сути монополист и может диктовать условия. Другой исполнитель не сможет разобраться в решении и для его выгоднее будет создать с нуля, чем проводить локальные доработки. Для заказчика оба варианта плохи.

Стоимость апгрейда

Почти любое решение в SharePoint требует дополнительных затрат при апгрейде платформы. Причем чем хуже сделано решение, тем дороже стоит его апгрейд. Даже если решение реально не надо переделывать, то исполнитель заложит в смету риск, никто ведь заранее не скажет где и когда оно упадет.

Стоимость обслуживания решения

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

Как бороться со скрытыми затратами

Большинство скрытых затрат происходят от дефектов решения, которые невозможно выявить на приемо-сдаточных испытаниях. Чаще всего это:

  • Непроработанность пользовательских сценариев
  • Дефекты в модели данных, усложняющие масштабирование
  • Низкое качество кода, большое количество дефектов в реализации
  • Дефекты сценариев развертывания
  • Решение не адаптировано к работе в довольно динамичной среде SharePoint

А теперь собственно как бороться:

Пилотные проекты

Проекты SharePoint несут большую степень неопределенности при старте. Сделать успешное решение, для масштаба компании в несколько тысяч человек, почти невозможно. Нужно проверить что решение работает на небольшой группе, уточнить требования к нему, не потратив много денег. На стадии пилотного проекта можно пожертвовать качеством, но очень важно собрать обратную связь от пользователей. На маленьком масштабе проще удовлетворить всех пользователей и выделить ключевые потребности.

Ранее прототипирование

При разработке новой системы обязательно нужны прототипы. Сначала на бумаге, потом интерактивные, потом изготовленные непосредственно в SharePoint. Прототипы позволяют быстрее всего договориться всем участникам о том, какой будет результат.

Слабосвязные сервисы

Если выбирать между большой интегрированной системой и набором отдельных полезных сервисов, то обязательно надо выбирать второе. Отдельные сервисы дешевле, проще в создании и внедрении. Внутренняя сложность отдельных сервисов гораздо ниже большой системы, а SharePoint обеспечивает возможности интеграции между сервисами.

Если сделать хороший сервис для одного структурного подразделения, то совершенно необязательно его масштабировать на всю компанию. Можно просто продублировать сервис для каждого подразделения, а потом собрать данные для отчетности и анализа прямо в Excel.

Не пытаться покрыть 100% потребностей

Это очень важно. SharePoint, как и любая другая платформа имеет свои ограничения, то сделать на нем можно все что угодно, но некоторые вещи будут крайне дорогими. Тут нужно применять правило Парето: 20% усилий дают 80% результата. Остальные 80% лучше потратить на создание других сервисов.

Придерживайтесь best practices

Даже в официальной документации по платформе описаны сотни рекомендаций как надо делать. Кроме того множество книг содержат эти самые рекомендации. Отступая от этих рекомендаций вы повышаете скрытые расходы ваших решений на SharePoint. Нужна очень веская причина чтобы отступать от рекомендаций.

Design review

Для каждого сервиса необходимо проводить инспекцию дизайна ДО того как начнется разработка и внедрение. Даже если своих ресурсов нет для этого, то можно пригласить консультантов. Опытный архитектор SharePoint быстро поймет где источники скрытых затрат, глядя только на схему решения.

Проверка решений

По возможности делайте аудит кода. Для этого существуют инструменты, например SPCAF (http://www.spcaf.com/). А особо сложных случаях также можно привлечь консультантов.

Имейте все исходники и документацию

Часто подрядчики хотят зацепить клиента нехорошим способом – не отдавать исходники решений, продав при этом дорогой контракт поддержки. С самого начала работ с внешним исполнителем надо договориться о передаче имущественных прав на решение и исходных кодов заказчику. Кроме того требуйте наличие технического описания решения, которое говорит о том из каких частей состоит решение, как оно устанавливается и как предоставляется пользователю.

В идеале для этого необходимо использовать интегрированные среды разработки, желательно в облаке.

Заключение

Прочитав этот пост многие подумают, что уменьшение скрытых затрат ведет к увеличению затрат явных.

Исследования множества проектов разработки (Shull defects paper) говорят о том, что 20%-80% стоимости разработки занимает переделывание работы, связанное с исправлением дефектов. Разброс большой, точная величина зависит от уровня зрелости разработки у исполнителя.

Ранее я приводил таблицу результативности методов устранения дефектов (http://gandjustas.blogspot.com/2013/07/code-review-vs-testing.html). Прототипирование, инспекции дизайна и кода показывают одни из лучших результатов. В совокупности они могут дать до 95% устранения дефектов до релиза. Правильный подход к разработке может сократить общие затраты на создание решения более чем в два раза, добавив незначительные затраты на прототипирование и инспекции.

В том же исследовании указано, что затраты на создание сложносвязных систем вы разы выше, чем создание систем с малым количеством связей между компонентами. Именно поэтому стоит создавать небольшие сервисы, которые в дальнейшем объединять в системы. По моему опыту такой подход позволяет во много раз сократить совокупную сложность системы и позволяет плавно переходить от стадии прототипирования к масштабированию системы.

В итоге делать хорошие решения получается быстрее и выгоднее для обоих сторон.



Связанные элементы в SharePoint 2013

Вам наверное часто в решениях требовалось сделать возможность связать один элемент с другим. Причем не просто лукап сделать, а так чтобы можно было произвольно выбрать элемент и создать связь с ним.

Копая JSOM, я недавно обнаружил, что в SharePoint 2013 есть такой функционал.

“Изкаропки” он доступен в списке задач. У каждой задачи есть “связанные элементы”.

image

При нажатии на “добавить связанный элемент” появляется стандартный asset picker

image

Можно выбирать любой элемент в пределах коллекции сайтов.

Внутренности “связанных элементов”

“Связанные элементы” это кастомное поле с ID равным значению Microsoft.SharePoint.SPBuiltInFieldId.RelatedItems. Это поле скрытое и добавить его в список из интерфейса не получится. Но в решении вы совершенно спокойно можете добавить это поле в тип контента.

Сам касс поля определен в сборке Microsoft.SharePoint и доступен, в том числе, в Foundation. Для работы с полем доступны только клиентские API, серверный класс для них помечен как internal.

На клиенте можно обращаться с помощью классов SP.RelatedItemManager в sp.js (http://msdn.microsoft.com/en-us/library/jj838582.aspx) и Microsoft.SharePoint.Client.RelatedItemManager в сборке Micrsosoft.SharePoint.Client (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.relateditemmanager.aspx).

Если интересна реализация поля, то смотрите с помощью IlSpy класс Microsoft.SharePoint.RelatedItemManager в сборке Microsoft.SharePoint. Рендеринг поля описан в файле sp.ui.relateditems.js

Реализация поля предельно простая – в текстовом поле сохраняется сериализованный в json массив элементов Microsoft.SharePoint.RelatedItem. Есть ограничение – не более 9 связанных элементов. Скорее всего оно связано с необходимостью secutrity trimming ссылок на связанные элменты, а это делается крайне медленно в SharePoint. Для security trimming ссылок в ленте новостей используется поиск+кеширование, но функционал “связанных элементов” рассчитан на работу в foundation и не может использовать такие возможности.

Применение

Из-за ограничения количества связанных элементов использовать данную возможность для разработки большой системы не получится. Хотя во многих сценариях данное поле может заменить лукапы. Кроме того API позволит вычислять “транзитивное замыкание” связанных элементов.

Наибольший интерес “связанные элементы” представляют как пример качественно сделанного расширения платформы. Оно включает в себя Custom Field Type с контролом, API на сервере и на клиенте, рендеринг поля в формах и использование asset picker. Если будете делать что-то подобное, то изучите реализацию “связанных элементов”.



Code Review vs Testing

Почти все знают, что баг в программе, исправленный на этапе использования, стоит примерно в 100 раз дороже, чем исправленный до использования. Кто не верит – может почитать результаты исследования Shull defects paper.

Если спросить программистов какой метод исправления поиска и исправления багов наиболее эффективный, то большинство ответит - “тестирование”. И будут неправы…

Эффективность различных методов устранения ошибок

В книге МакКоннелла CodeComplete есть статистика (да-да, все её читали, но никто сходу не может вспомнить что там написано), которая разрывает мозг многим апологетам тестов.

Методика

Результативность в среднем

Regression test 25%
Informal code reviews 25%
Unit test 30%
New function (component) test 30%
Integration test 35%
Low-volume beta test (< 10 users) 35%
Informal design reviews 35%
Personal desk checking of code 40%
System test 40%
Formal design inspections 55%
Formal code inspections 60%
Modeling or prototyping 65%
High-volume beta test (> 1000 users) 75%

То есть в среднем все методы тестирования менее результативны, чем формальные инспекции дизайна и кода. А если еще поделить результативность на затраченное время, то review становится в разы эффективнее тестирования.

Как делать review

Для начала надо почитать того же МакКоннелла, у него все более чем подробно описано. Ключевые моменты:

  • Чтобы проводить инспекции нужны чек-листы.
  • Темп code review составляет 120-200 строк в час.
  • Инспекторов должно быть как минимум два.
  • Должны быть адекватно описаны требования к коду: быть полными и не содержать противоречий и неточностей.
  • Код должен компилироваться.
  • Код должен быть проверен разработчиком, как минимум выполнять основные сценарии на его машине.

В настоящий момент существует множество инструментов для code review, в том числе встроенных в средства разработки, поэтому необходимость в review meeting значительно ниже. Возможно для review верхнеуровневого дизайна потребуется совещание, но для review кода митинги скорее вредны.

Как повысить эффективность code review

Средняя продолжительность продуктивного писания кода – 4-5 часов в день. То есть 3-4 часа в день программист не занимается написанием кода, или занимается, но лучше бы этого не делал. Можно скорректировать время работы программистов, чтобы 4 часа в день они писали код, два часа делали review, еще два часа занимались проектированием, митингами и административными задачам. То есть review получается практически бесплатно.

Команда в 3-4 человека будет вполне успевать проводить review написанного за день кода в оставшиеся 2 часа после кодирования.

Значительную часть review можно автоматизировать, есть множество инструментов, которые проверяют качество кода.

Если все так круто, то почему же все занимаются тестированием?

Ответ на этот вопрос я долго искал, пока не наткнулся на презентацию Эрика Липперта о психологических аспектах анализа кода (http://www.slideshare.net/Coverity/the-psychology-of-c-analysis-24025354). Несмотря на то, что в презентации рассказывается об автоматизированном анализе, причины недоверия более чем верны для code review.

Основная причина – психология программистов. Для проведения review необходимо взаимодействовать с людьми, получать от них замечания к своему коду. Психологически это гораздо тяжелее, чем писать тесты к своему коду.

Вы наверное и сами обращали внимание, что смотреть чужой код и находить в нем ошибки бывает даже интересно. А вот когда ваш код кто-то смотрит и указывает на ошибки в нем – уже вызывает дискомфорт, а у некоторых откровенное неприятие.

Кроме того тесты это тоже код, это значит менеджер может посмотреть чем программист занимался. А еще лучше если менеджер посмотрит результаты тестового покрытия, хотя эта величина практически бесполезна.

Заключение

Несколько статей про code review, в них есть много интересных ссылок на исследования и книги:

Немного про SharePoint. Джентльменский набор для анализа кода:

ЗЫ. Все написанное выше не означает что надо бросить тестирование и все силы перекинуть на review. У того же МакКоннелла написано, что наибольший эффект достигается при применении минимум трех методик.



SharePoint и Ajax

Как вы думаете, сколько способов сделать ajax запрос в SharePoint? А без jQuery и дополнительных библиотек? Нет, XMLHttpRequest руками писать на надо.

Sys.Net.WebRequest \ Sys.Net.WebRequestExecutor

Эти классы находятся в библиотеке MicrosoftAjax. Она подгружается на каждой странице SharePoint и вы можете использовать её на своих страницах.

Класс Sys.Net.WebRequest описывает параметры запроса, а Sys.Net.WebRequestExecutor, вернее его наследник, выполняет запрос с указанными параметрами. Можно создавать свои реализации WebRequestExecutor, например для тестирования или для проксирования запросов.

Недостаток этих классов в чрезмерной многословности.

var request = new Sys.Net.WebRequest();         
request.set_url(url);
request.set_httpVerb("GET");         
request.add_completed(function(executor, eventArgs) {             
    if(executor. get_responseAvailable()) {
        //do stuff
    }
});


                
            


SPTypeScript 1.1

Рад сообщить, что недавно был выпущен новый релиз SPTypeScript версии 1.1

Основные нововведения

Совместимость с TypeScript 0.9

TypeScript 0.9 имеет несколько ломающих изменений, которые коснулись большинства описаний библиотек, в том числе SPTypeScript. В релизе 1.1 все определения совместимы с TypeScript 0.9

Применение generic-типов для коллекций

SharePoint в JSOM использует аналог типов IEnumerable\IEnumerator из языка C#. Ранее это приводило к слаботипизированному и громоздкому коду. В новом релизе добавлены типы параметры в интерфейсы IEnumerable\IEnumerator и все типы-коллекции. Теперь код обработки коллекций стал более типизированным, но не менее громоздким.

image

Добавлены описания типов для mQuery

Ранее я писал про библиотеку mQuery в SharePoint 2013. SPTypeScript 1.1 включает полное описание этой библиотеки.

Пример использования:

SP.SOD.executeFunc("mQuery.js","m$", function() {
    m$.ready(function() {
        var d = new Date();
        var month = d.getMonth();
        var date = d.getDate();
        var year = d.getFullYear();
        m$('#pageTitle').append("<div style='float:right'>" + month + "/" + date + "/" + year + "</div>"); 
    }); 
});

Также в проекте SPTypeScript вы найдете пример использования mQuery.

Добавлены описания для класса SPClientAutoFill

Этот класс реализует функциональность autocomplete (typeahead) и имеет очень простой API, доступный в любом решении для SharePoint.

image

В прошлом посте я описывал применение этого визуального компонента. В проект включен пример использования.

Добавлены примеры кастомизации форм

  • Добавление вкладок на форме элементов списка
  • Кастомное поле списка с валидаторами
  • Кастомизация обычного lookup поля с помощью поиска и SPClientAutoFill

Кроме того

  • Добавлены описания классов SP.Utilities
  • Улучшены описания типов Client Side Rendering и SP.UI

Доступность на NuGet

Самое главное улучшение совершенно не связано с определениями или примерами. SharePoint.d.ts теперь доступен в NuGet http://nuget.org/packages/sharepoint.TypeScript.DefinitelyTyped/

Достаточно в Package Manager консоли выполнить команду:
PM> Install-Package sharepoint.TypeScript.DefinitelyTyped

Заключение

Качайте дефинишены, используйте TypeScript, задавайте вопросы, пишите замечания  и пожелания. Ваши фидбек очень важен для нас.



Автокомплит в SharePoint 2013: пошаговое руководство

Данный функционал был найден Антоном Вишняковым и описан в посте в его блоге. Большая часть контента данного поста взята из его блога с его разрешения.

Вы уже видели новый элемент управления для выбора людей в SharePoint 2013? Этот элемент управления был сильно улучшен по сравнению с предыдущей версией SharePoint. Теперь этот элемент можно использовать в клиентском коде и спокойно внедрять на своих страницах. Кроме того появился отличный функционал автозаполнения.

070713_0434_LeveragingS1[1]

Замечательная новость: вы можете использовать функционал автозаполнения с любым текстовым полем. Эту функцию реализует контрол  SPClientAutoFill. Он находится в файле autofill.js в _layouts/15. Давайте посмотрим как сделать решение с его помощью.

Шаг первый: разметка и стили

Для того чтобы использовать SPClientAutoFill вам потребуется следующая разметка:

<div style='position: relative;'>
    <input type='text' id='autofillElement' />
    <div class='sp-peoplepicker-autoFillContainer' 
            id='autofillContainer' />
</div>


                
            


Вебинар по Storage Optimization в SharePoint

В среду, 19.06.2013, будет проводиться вебинар на тему повышения эффективности хранения большого объема данных  в SharePoint.

Я буду рассказывать про основные проблемы, пути решения и best practicies. Партнеры из компании AvePoint расскажут о продуктах, которые помогут добиться результатов.

Целевая адуитория – архитекторы и администраторы порталов SharePoint.

Ссылка на описание и регистрацию: https://eu.avepoint.com/resources/webinars/?tab=ru&utm_source=iteco&utm_medium=webinar&utm_campaign=optimisation

Присоединяйтесь все, буду раз всех видеть или слышать. Количество мест ограничено.

UPD. Запись выложена здесь - http://eu.avepoint.com/assets/movie/webinar/russian/Webinar-Optimisation-Russian-June19-2013.html



Слайды с SPCUA и DevCon

За последние две недели я успел выступить с двумя докладами на конференция SharePoint Conferencе Ukraine 2013  в Киеве и DevCon 2013 в Москве.

Первый доклад посвящен вопросам аутентификации и авторизации в приложениях SharePoint 2013 (apps).

Второй доклад, который я делал совместно с Маратом Бакировым, о том как создавать приложения в SharePoint 2013.

Видеозаписи выступлений будут доступны позже.



Разработка приложений SharePoint 2013 с помощью TypeScript

Прошлый раз я описывал преимущества использования TypeScript для разработки приложений.

В этом посте я покажу как TypeScript поможет разрабатывать приложения для SharePoint 2013. В SharePoint 2013 были улучшены возможности разработки клиентских приложений на JavaScript. Это касается не только API, доступных на клиенте, но и механизмов поставки и развертывания приложений, инструментов разработчика. Более того, многие функции самого SharePoint 2013 реализованы и могу быть кастомизированы с помощью JavaScript.

SharePoint 2013 предлагает два вида API для использования на клиентской стороне: Client-Side Object Model (CSOM) и REST API. REST API позволяет манипулировать объектами на сервере используя REST (OData) веб-сервис. CSOM представляет из себя набор классов, семантически эквивалентных серверной объектной модели SharePoint. CSOM доступна как для JavaScript (также называют JSOM – JavaScript Object Model) , так и для .NET. Но в JavaScript, в отличие от .NET, недоступны метаданные и типизация. В этой статье будет рассмотрено именно применение JSOM.

TypeScript позволяет описать типы для JSOM и использовать статическую проверку типов и intellisense при разработке приложений. К сожалению готовых определений типов для SharePoint 2013 в открытом доступе нет.

Я и Андрей Маркеев создали проект на CodePlex, в котором сделали определения типов и кучу примеров приложений на TypeScript для SharePoint 2013. Ссылка на проект - http://sptypescript.codeplex.com/

Пример приложения

Для примера создам приложение, позволяющее отслеживать время на рабочем месте.

image

Подготовка

Для начала необходимо:

Для того чтобы при сборке проекта выполнялась компиляция  TypeScript необходимо добавить в .csproj файл следующие элементы:

<PropertyGroup>
    <TypeScriptTarget>ES3</TypeScriptTarget>
    <TypeScriptIncludeComments>true</TypeScriptIncludeComments>
    <TypeScriptSourceMap>true</TypeScriptSourceMap>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets" />

 

Библиотеки и определения

Визуальный интерфейс будет создан с помощью библиотеки knockoutjs с расширением koLite.

Для того чтобы использовать эти библиотеки в проекте необходимо добавить следующие NuGet пакеты:

  • KoLite (knockoutjs добавится автоматически)
  • jquery.TypeScript.DefinitelyTyped
  • knockout.TypeScript.DefinitelyTyped
  • kolite.TypeScript.DefinitelyTyped

Последние три пакета представляют из себя .d.ts файлы, которые описывают типы для TypeScript.

Для работы с JSOM в TypeScript надо добавить в проект файл SharePoint.d.ts, который можно найти по ссылке. NuGet пакет будет доступен в ближайшее время.

Загрузка скриптов по требованию

В SharePoint есть свой загрузчик скриптов по требованию в классе SP.SOD. Подробное описание можно найти в этом посте.

Код загрузчика скриптов приложения:

///<reference path="typings/SharePoint.d.ts" />
///<reference path="typings/jquery/jquery.d.ts" />
///<reference path="typings/knockout/knockout.d.ts" />


                
            


Запись с доклада на SPC UA 2012

Прошел почти год с того момента, как я выступал на конференции в Киеве. Наконец-то организаторы выложили запись выступления.

Смотреть тут: http://sharepoint-channel.com/stanislav-vyshhepan-iskusstvo-upravleniya-sharepoint-kak-poluchit-maksimalnuyu-vygodu-dlya-biznesa-videozapis-doklada-na-spcua-2012



Как создавать надежные приложения в серверном коде для SharePoint

Несколько советов о том как сделать код более надежным и устойчивым:

  1. Получайте списки только с помощью такой конструкции 
    web.GetList(SPUrlUtility.CombineUrl(web.Url, listUrl)

    Получение по Title списка ненадежно, так как Title может быть изменен пользователем без вашего ведома.
  2. При получении значений полей элементов списка используйте Id поля или его StaticName.
    listItem[FieldId] //Если вы деплоите это поле или это встроенное поле
    listItem[FiledStaticName] //Если поле нестандартное и не вы его деплоите

    Обращение по Title поля ненадежно, так как Title может меняться.
  3. Для стандартных полей используйте классы SPBuiltInFieldId и Microsoft.SharePoint.Publishing.FieldId
  4. Для обращения к стандартным типам контента используйте SPBuiltInContentTypeId и Microsoft.SharePoint.Publishing.ContentTypeId
  5. Используйте класс Convert для получения типизированного значения поля
    Convert.ToDateTime(listItem["Created"])
    Для разных типов полей SharePoint может возвращать разные типы данных. Например числа могут возвращаться как строки. Кроме того Convert корректно обрабатывает null. Даже если у вас Required поле, то все равно может вернуться null по многим причинам.
  6. Добавление элементов в список
    list.AddItem() //только так
    //list.Items.Add() - ТАК ДЕЛАТЬ НЕЛЬЗЯ
  7. Количество элементов в списке
    list.ItemCount //Только так
    //list.Items.Count – ТАК ДЕЛАТЬ НЕЛЬЗЯ
  8. AllowDeletion

    Используйте AllowDeletion=”false” для списков и полей, которые вы деплоите в своем решении
  9. Sealed

    Используйте Sealed=”true” для полей и типов контента, которые вы деплоите в своем решении
  10. Количество элементов в результатах

    Обязательно указывайте RowLimit свойство при получении элементов с помощью SPQuery или KeywordQuery
  11. Проверка активации фич

    В своем коде обязательно проверяйте, что необходимые для работы фичи активированы на узле\коллекции.
  12. Деплой веб-части вместе со списками

    Если вы создаете веб-часть, которая обращается к списку, в том же решении, то обязательно поместите в одну фичу уровня Site. Внутри веб-части получайте список с RootWeb (см пункт 1).
  13. Не использовать RunWithElevatedPriveleges

    Используйте конструктор SPSite с SPUserToken. Передавайте SPUserToken.SystemAccount.

    Использование RunWithElevatedPriveleges оправдано только когда вы хотите обратиться к веб-сервису\БД от имени учетной записи пула приложений.

    И не стоит забывать, что работает данный метод только в контексте веб-приложения.

  14. Не модифицировать SPPersistedObject в контексте веб-приложений

    Это просто не работает. Можно обойти, но не стоит.
    Все объекты, унаследованные от SPPersistedObject, должны создаваться\изменяться в фичах уровня Farm и WebApplication или в задачах таймера.

  15. Не обращаться к ресурсам компьютера

    Их просто может не быть. Даже если вы при активации фичи создаете все что необходимо, то новый сервер может быть введен в ферму без переактивации фич.

    Это касается фалов, вне тех что деплоятся в решении, ключей реестра, event source  в windows event log и другого.
  16. Не использовать параметры в web.config

    Код SharePoint может быть запущен не только в веб-приложении, но и в timerjob, powershell, процессе-домене службы поиска или в любом коде на сервере.

    Естественно не везде будет работать стандартный класс ConfigurationManager(WebConfigurationManager).

Если есть еще советы – пишите, обязательно дополним список.



Javascript-enabled SharePoint WCF services

К сожалению очень мало толковой информации о том, как создать WCF веб-сервис для SharePoint, который будет доступен как для WS-* клиентов, так и для Javascript.

Да-да, я знаю что уже вышел SharePoint 2013 и .NET 4.5, то что WCF уже не модно, и надо юзать WebAPI и REST. НО не факт что можно будет расширять API для SharePoint 2013, а WebAPI в SharePoint 2013 не работает (или по крайней мере это еще никто не сделал).

Так что пока используем WCF, благо его возможностей более чем достаточно для решения задачи.

Для начала надо поставить расширение студии CKS Dev (правильно говорить “секасдев”, @amarkeev гарантирует это), в нем есть шаблон для WCF сервиса

image

Этот пункт создает веб-сервис с BasicHttpBinding.

В SharePoint не обязательно параметры указывать в web.config, достаточно указать Factory в .svc файле, что и делает данный шаблон.

Какие есть Factory и зачем они нужны можно узнать по ссылке.

В принципе можно и этот сервис использовать в javascript коде, но придется долго и мучительно генерировать и парсить XML для SOAP. Чего делать крайне не хочется.

Для того, чтобы работать с теплым ламповым JSON достаточно сделать несколько изменений.

  1. Скопировать .svc файл и поставить ему те же параметры развертывания, что у исходного сервиса. Я даю сервисам имя <servicename>.json.svc
  2. В новом файле .svc зменить MultipleBaseAddressBasicHttpBindingServiceHostFactory на MultipleBaseAddressWebServiceHostFactory
  3. В интерфейсе сервиса добавить атрибуты методам, например
    [ServiceContract]
    public interface ITestService
    {
        [OperationContract]
        [WebGet(BodyStyle = WebMessageBodyStyle.Bare, 
                RequestFormat = WebMessageFormat.Json, 
                ResponseFormat = WebMessageFormat.Json)]
        //[WebInvoke(Method="POST",
        //        BodyStyle = WebMessageBodyStyle.Bare,
        //        RequestFormat = WebMessageFormat.Json,
        //        ResponseFormat = WebMessageFormat.Json)]
        string HelloWorld();
    }

И все, код сервиса править не надо. Атрибуты WebGet и WebInvoke можно найти в сборке System.SeviceModel.Web.

Код для вызова сервиса (javascript):

var webServerRelativeUrl = _spPageContextInfo.webServerRelativeUrl != "/" 
                           ? _spPageContextInfo.webServerRelativeUrl 
                           : "";


                
            


Как писать правильный код для SharePoint

Сегодня наткнулся на этот потрясающий пост на GotDotNet. Код в 20 строк изобилует практически всеми ошибками, которые можно совершить при разработке для SharePoint.

Некоторое время назад я написал небольшой список правил, которых следует придерживаться при разработке веб-частей, большинство их правил также верны и для разработки других артефактов.

Привожу текст письма с правилами “как есть”:

Господа, давайте сразу делать веб-части для главной НОРМАЛЬНО

1. Никаких visual web part, используйте sandboxed visual web part

2. Никаких ссылок на скрипты и css в разметке, используйте классы CssRegistratoin и ScriptLink

3. Получение списков только через web.GetList(SPUrlUtility.CombineUrls(web.Url, listRelativeUrl)

4. Списки для веб-частей на главной лежат в корневом сайте, доступ к которому только через SPContext.Current.Site.RootWeb

5. Никаких вызов конструкторов SPSite и site.OpenWeb крайней необходимости

6. В JS учитывайте что может быть много экземпляров веб-частей на странице, передавайте в скрипты id элементов с помощью control.ClientID

7. Так как веб-части на страницу могут быть добавлены после постбека – не используйте Page.IsPostBack для проверки первой загрузки

8. Лучший вариант – грузите данные в createchildcontrols

9. Используйте репитеры вместо склейки HTML в коде

10. Вставляйте везде SPMonitoredScope

11. Структурируйте код так, чтобы загрузка данных была отделена от генерации HTML (чтобы можно было кеширование прикрутить)

12. Отключайте по возможности ViewState

13. Обрабатывайте ошибки, чтобы при ошибке в веб-части не падала страница. Надо обрабатывать SPException, FileNotFoundException (сайт не найден, нет доступа), DirectoryNoFoundException (список не найден, нет доступа)

14. Если напишите try с пустым catch – оторву йайтса

15. Ошибки пишите в лог и выводите в красном Literal на страницу

16. Используйте только exception.ToString()

17. Корректно обрабатывайте случаи отсутствия элементов при выводе

18. На странице может быть две одинаковые веб-части и они должны корректно работать

Две ссылки по теме:

http://msdn.microsoft.com/en-us/library/bb985502(v=office.12).aspx

http://msdn.microsoft.com/en-us/library/dd583141(v=office.11).aspx

PS. Пункт 1 актуален для Visual Studio 2010, в 2012 такие веб-части создаются по-умолчанию.



5 правил логирования в SharePoint

Большая часть кода, написанного для SharePoint работает в крайне непредсказуемой среде.Полностью отлаженный на компьютере разработчика код может совершенно “необъяснимо” падать в целевой среде. В этой ситуации очень важно логировать происходящее в вашем коде.

Тема логирования очень любима многими разработчиками. Одни предпочитают писать свои велосипеды, другие пользуются готовыми фрейморками, третье используют возможности ОС.

Если вы разрабатываете решения для SharePoint, то вам необходимо придерживаться следующих правил:

0. Не используйте фреймворки

Даже если вы очень любите log4net, или NLog, или EventLog, или System.Diagnostics.Trace, или пишете свой велосипед, то никогда не используйте ничего из вышеперечисленного.

В SharePoint существует своя система логирования, называемая Unified Logging System (ULS). Если у вас возникает вопрос чем ULS лучше чем <подставьте сюда свой любимый фреймворк>, то вот основные причины:

  • ULS уже используется компонентами SharePoint, используя другую систему вам придется собирать логи в нескольких местах
  • ULS гибко настраивается из Central Administration и PowerShell
  • ULS умеет писать в Windows Event Log, не требуя при этом привилегий
  • ULS обеспечивает сжатие текстовых логов на диске
  • ULS не требует правки web.config (что очень важно для многосерверной фермы)
  • SharePoint умеет собирать логи ULS (и не только их) со многих серверов в одну базу
1.  В простых случаях не делайте ничего

SharePoint сделан так, что необработанные исключения внутри процессов SharePoint попадают в ULS.  В случае возникновения ошибки очень легко будет в ULS найти stack trace, а если включить уровень логированя VerboseEx, то и все запросы к базе со статистикой.

Для просмотра логов удобнее всего применять утилиту UlsViewer, для русской версии Windows Server может понадобиться патч.

Есть одно исключение из этого правила – веб-части. Если веб-часть в full trust падает с ошибкой, то пользователь увидит только страницу ошибки. Причем если ошибка вызвана персонализированными свойствами, то ошибку будет сложно устранить. Хорошим тоном при разработке веб-частей является не вывод исключения, а  отображение информации как ошибку исправить.

2. Используйте SPMonitoredScope везде

Класс SPMonitoredScope очень прост в использовании:

using (new SPMonitoredScope("My Monitored Scope"))
{
    // Do Stuff...
}


SharePoint 2013 для разработчиков

Недавно в открытом доступе появилась preview версия SharePoint и Ofiice 2013. Про возможности для бизнеса и конечных пользователей напишут еще не раз, гораздо интереснее как будет выглядеть разработка под новую версию платформы.

1. Javascript

Если вы еще не знаете Javascript, то бросайте все и срочно изучайте.

В новой версии javascript будет использоваться для:

  1. Рендеринга представлений и форм списка
  2. Рендеринга результатов поиска
  3. Создания приложений Office и SharePoint
  4. Большинства кастомизаций интерфейса

Большая часть кода для SharePoint и Office 2013 будет написана на JS. И почти никакого xsl.

2. Поиск

В SharePoint 2013 поиск стал основным инструментом для доступа к данным. С помощью поиска можно обратиться к любым данным, которые есть в SharePoint. Даже в 2010 версии поиск был очень мощным инструментом, позволяющим работать с большими объемами данных и сложными структурами сайтов. В новой версии поиск дополнился многими возможностями. Если вы еще не знакомы с поиском SharePoint, то стоит это исправить. Возможно и для версии SharePoint 2010 найдете много полезных применений поиска в решениях.

Особенно важно что в версии 2013 поиск может выдавать результаты почти в реальном времени.

3. Social

Если раньше SharePoint ассоциировался со словом collaboration (совместная работа), то с версии 2013 он будет ассоциироваться со словом social (социальный). Лента сообщений, шаринг, фолловинг, комментирование, лайки, сообщества, рейтинги, бейджи – теперь это не просто есть в SharePoint (оно и версии 2010 было), теперь это основной инструмент взаимодействия.

Конечно старые механизмы, вроде утверждения, согласования, рабочих процессов, задач и email никуда не делись. Но новая социальная платформа позволяет работать в более динамичной и менее структурированной среде. Множество решений будут ориентироваться на социальные возможности.

4. Workflow Foundation 4

Кто не в курсе – WF4 написан с нуля и не имеет почти ничего общего с предыдущей версией. В SharePoint 2013 есть поддержка новых рабочих процессов, работающих на движке Workflow Foundation 4.

В отличие от предыдущих версий в WF4:

  1. Процессы декларативны, задаются в XML, даже если создавать процессы в Visual Studio.
  2. Процессы в WF4 полны по Тьюрингу, то есть могут описать любой алгоритм.
  3. Процессы, созданные в SharePoint Designer 2013 могут иметь циклы и переходы к предыдущим состояниям.
  4. Процессы могут общаться с внешним миром посредством HTTP запросов. Так как SharePoint 2013, наряду с клиентской объектной моделью, предоставляет REST интерфейс, то с помощью HTTP запросов можно сделать (почти) все.
  5. Фактически нельзя использовать .NET код для Workflows.

Последнее ограничение довольно серьезно, но его можно обойти создавая свои сервисы, или запуская workflow старой версии, которые присутствуют в версии 2013 без изменений.

WF4 в SharePoint 2013 стал middleware для решений.

5. Cloud

Облака повсюду. В SharePoint 2013 самые большие вложения сделаны именно в развитие облачных решений. Это не могло не повлиять на архитектуру.

В основе новой архитектуры лежит идея, что любой кастом должен выполняться не на машинах фермы SharePoint. Например упомянутый выше WF4 фактически выполняется в отдельном сервисе (Windows Azure Workflow), сервис общается с SharePoint  с помощью клиентской объектной модели.

Новая модель приложений (apps) для SharePoint требует соответствия такой архитектуре и вообще  не позволяет выполнять код на сервере SharePoint.

Это все означает что придется много использовать HTTP, а основным инструментом отладки станет Fiddler.

6. Новый дизайн и темы

Они настолько прекрасны, что такой класс решений, как брендинг портала совместной работы станет не нужен. Более того, в документации теперь написано что изменение стандартной мастер-страницы SharePoint 2013 не поддерживается.

Для порталов публикации облегчили процесс создания нового дизайна. Теперь верстальщикам гораздо меньше потребуется знать SharePoint чтобы сделать на нем сайт.

7. Claims аутентификация и OAuth

В SharePoint 2013 основной вид аутентификации – claims. Кто еще не знаком с ней, то надо срочно исправить этот пробел. Claims аутентификация в SharePoint таит некоторые подводные камни и, к сожалению, не любой код, работающий в режиме classic будет корректно работать в режиме claims.

Также появилась возможность аутентификации по протоколу OAuth. Вам обязательно придется использовать OAuth для приложений.

Что почти не изменилось

1. Серверная объектная модель

WSP пакеты, фичи, CAML и глюки парсера, unmanaged код под капотом, списки и библиотеки – все это осталось. Некоторые новые возможности появились, но незначительно. Это все работает, поддерживается (в on-premise и sandbox) и может быть применено в решениях.

Несмотря на то что SharePoint 2013 собран под .NET 4, я не нашел что в объектной модели используется из новой версии фреймворка.

2. Внутренняя архитектура

Все также есть Service Applications. Появилось несколько новых типов сервис-приложений, но больших изменений нет.

Заключение

Большая часть изменения новой версии направлена на Office 356. Некоторые приложения будут работать в Office365 и не будут в on-premise варианте.  С другой стороны российские реалии говорят о том, что компании неохотно размещают свои данные в облаках.

Поэтому основной фокус в ближайшее время останется на разработке решений для on-premise. А новая модель приложений с marketplace в этому случае будет востребована гораздо слабее, чем хотелось бы Microsoft.

Более подробно об этом в следующий раз.



Веб-каст про создание решений в SharePoint

На днях провел веб-каст для коллег с демонстрацией как можно создавать артефакты SharePoint в браузере и SharePoint Designer, а потом переносить их в Visual Studio для создания WSP.

Это мой первый опыт веб-каста, он записан в один заход и почти без предварительной подготовки. Прошу не судить строго.

 

Ссылки, используемые в веб-касте:



Процесс создания решений на SharePoint.

Недавно на форуме один посетитель задал простой вопрос, который превратился в очень интересную дискуссию.

Возможно ли в запросе CAML сделать так, чтобы выбирались только элементы с 10 по 20 к примеру? Это необходимо для организации пейджинга блога.

Краткий ответ: нет, так сделать нельзя и, по большому счету, не нужно.

Когда топикстартеру задали вопрос зачем же все-таки так делать он ответил:

так задачу поставили( надо видеть количество страниц и переходы на них...

А дальше еще интереснее:

Руководство сказало "надо", мы сказали "есть!"))

Как ни парадоксально, но тем кто лучше всех должен разбираться в решениях на некоторой платформе совершенно все равно насколько полезны и эффективны их решения. Собственно само решение диктуется людьми (в данном случае “руководством”, иногда бывают аналитики или менеджеры), которые заведомо хуже в этом разбираются.

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

Для начала стоит заметить что в SharePoint есть шаблон сайта блога. Ему конечно далеко до профессиональных блогодвижков, но в некотором роде задачи свои решает и неплохо кастомизируется.

Но тут кому-то пришло в голову что там не хватает номеров страниц и перехода по ним. Попробуем разобраться откуда такая мысль.

Вариант первый

Возможно человек видел нечто подобное в другом блогодвижке. SharePoint при показе списка учитывает не только статус публикации, но еще и утверждение, основные и дополнительные версии, а также разрешения вместе с наследованием причем в реальном времени.

Скорее всего, именно из-за этих фич используется SharePoint, а не опенсорсная CMS. Но наличие таких фич  приводит к невозможности перехода к конкретной странице и подсчету их количества.

Чаще всего такие требования являются попыткой восполнить пробел обучения путем построения на SharePoint другой, более знакомой, системы.

Создание такой системы – медвежья услуга.  Стандартные возможности SharePoint протестированы, документированы и работают. Создавая свое, похожее но другое, вы не можете вложить столько же сил в тестирование и документирование, сколько вложил Microsoft. Скорее всего решение будет работать гораздо хуже стандартного. Кроме того созданное решение надо поддерживать, апгрейдить итд.

Совокупная стоимость владения повышается, а эффект очень локален. Ведь новая система более привычна узкому кругу лиц.  Гораздо более правильное решение в данном случае – обучить пользоваться возможностями SharePoint.

Вариант второй

Возможно людям действительно надо переходить на несколько страниц вперед. Стоит понять почему такое происходит. Скорее всего то что нужно не находится на первой странице.

В этом случае правильное решение – настроить представления и\или поиск таким образом чтобы нужная информация была на первой странице.

Вариант третий

Кнопочки с номерами страниц – элемент визуального дизайна портала. Такое часто случается когда дизайн создается без оглядки на возможности SharePoint. То есть изначально полезности  в этом элементе нет, есть только визуальная “изюминка”.

В этом случае можно придумать другую “изюминку”. Например сделать unlimited scroll на странице списка. Такой элемент гораздо более удобен для пользователя, но при этом не требует подсчета количества страниц.

Заключение

Процесс создания решения это не написание кода. Особенно в среде SharePoint, где много стандартных возможностей, стоит набольшее внимание уделять пониманию решаемых проблем и поиску консенсуса (не компромисса).

PS. Этот вопрос подробно описан в книге Брукса Design of Design. Рекомендую всем к прочтению.



Другие 3 фичи SharePoint о которых не знает вообще никто

В предыдущем посте я рассказывал про малоизвестные фичи SharePoint. О них не написано в книгах, мало информации в MSDN и только в паре блогов можно прочитать о них хоть что-нибудь.

В этом посте я расскажу про 3 абсолютно никому неизвестные фичи, которые были были найдены мной и коллегами в SharePoint. Скорее всего другой информации по этим фичам вы не найдете.

Третье место

Третье место в хит-параде занимают атрибуты Len и MoreText для элемента FieldRef во ViewFields в схеме CAML запроса (SPQuery). В документации эти атрибуты отсутствуют.  Если указать эти атрибуты для текстового поля, то SharePoint в этом поле вернет урезанную строку, которая вмещается в указанное в Len количество символов, в конце допишет текст, указанный в MoreText.
Причем обрезка текста происходит по границе слова, а не просто по количеству символов.  К сожалению не учитывается Html разметка.

Вот такой код:

using (var site = new SPSite("http://localhost"))
{
    var web = site.RootWeb;
    var list = web.GetList("Lists/Tasks");
    var query = new SPQuery()
    {
        ViewFields = "<FieldRef Name='Body' Len='20' MoreText='...'/>",
        ViewFieldsOnly = true
    };


                
            


3 фичи SharePoint о которых не знает почти никто

Private folder

Третье место в хит-параде почти неизвестных фич занимает каталог _private (начинается с символа подчеркивания) в виртуальной файловой системе SharePoint. Этот каталог находится в корне каждого узла и недоступен для внешнего HTTP запроса, только для API. Таким образом в этом каталоге можно хранить приватные данные, настройки и чтобы они не были доступны непривилегированным пользователям.

image

SPList.EnforceDataValidation

Второе место в хит-параде занимает это простое свойство, описание которого можно посмотреть по ссылке.
Если создать обязательное lookup поле, то в случае отсутствия элементов в lookup списке можно сохранить элемент с пустым значением lookup. Аналогичные проблемы можно получить и с другими полями если записывать данные в список с помощью SPWeb.ProcessBatchData. При SPList.EnforceDataValidation = true сам SharePoint дополнительно проверяет корректность данных.

Count related lookup

Первое место в хит параде достается особому типу lookup поля. Создав в списке A lookup колонку на список B можно потом создать в списке B lookup на список A. Это поле будет посчитывать количество связанных элементов.

image

image

Тоже самое доступно в API через свойство SPFieldLookup.CountRelated.

Далее еще 3 незвестные фичи.



Очередная встреча RUSUG 26.04.2012

Очередная встреча RUSUG состоится 26 апреля, в четверг. Пройдёт она, традиционно, в Технологическом центре компании Microsoft.

Первым докладчиком стану я, буду выступать с докладом «SharePoint Governance для разработчиков». В докладе пойдет речь о том как планировать, создавать и управлять решениями на SharePoint. Какие инструменты для этого есть в SharePoint, как их эффективно использовать и расширять.

Второй доклад будет посвящён лучшим практикам в настройке SQL Server для работы с SharePoint. Об этом расскажет Максим Хлупнов, Архитектор Технологического центра Microsoft.

Планируется проведение трансляции мероприятия, на которую необходима регистрация.

Регистрация на мероприятие и трансляцию: http://rusug.net/Lists/Apr2012Reg/NewForm.aspx



Я участвую в SPCUA 2012.

25 апреля пройдет событие года по теме SharePoint в СНГ – конференция SharePoint Conference Ukraine 2012 (http://spcua.com/). Генеральный партнер конференции Microsoft Украина, организатор – Lizard Soft (http://lizard-soft.com).

Конференция собрала докладчиков и участников не только со всего СНГ — но и из США и Европы. Ее именитыми докладчиками стали Майкл Ноэль (Michael Noel), Пол Свайдер (Paul J. Swider), Павел Вробель (Pawel Wrobel). Microsoft делегировала на конференцию докладчиков из ЕС, российского и украинского офиса Microsoft. Партнеры конференции из Австралии, Великобритании, Польши, России и Украины.

А также на конференции я буду читать доклад “Искусство управления SharePoint: как получить максимальную выгоду для бизнеса” и отвечать на вопросы.



Жириновский о SharePoint

jirinovskiy-on-sharepoint

via @avishnyakov



SharePoint + Javascript + Visual Studio = Love

Для тех кто еще не знаком с клиентской объектной моделью SharePoint, настоятельно рекомендую ознакомиться с ней. Client OM доступна как в C# (.NET и Silverlight), так и в Javascript.

.NET разработчики обычно не любят javascript, считают его убогим языком, приводящим к куче ошибок. И они в чем-то правы… Основной причиной называют динамическую типизацию и интерпретируемость javascript. На самом деле разработчика нужна не типизация и компиляция, а проверка кода до запуска и подсказки по коду. Обе возможности доступны в Visual Studio с расширениями.

Проверка кода до запуска

Для этого в галерее расширений visual studio есть два расширения:

  1. JSLint – встроенный в VS инструмент проверки кода javascript, который можно найти по адресу http://www.jslint.com/
  2. Javascript parser – расширение, которое парсит js код на лету (читай показывает ошибки) и предоставляет навигацию по коду.

Эти два расширения позволяют отловить наиболее частые ошибки в коде.

image

Кроме того рекомендую установить jscript editor extensions чтобы редактор был больше похож на редактор кода C#.

Подсказки по коду aka Intellisence

Эта возможность доступна начиная с Visual Studio 2008, но о ней до сих пор знает катастрофически малая часть разработчиков.  Чтобы intellicence для js заработал в visual studio, необходимо visual studio дать подсказку откуда брать файлы.

Если вы пишите javascript код в html\aspx\ascx\materpage файлах, то vs автоматически подтягивает все .js файлы из тегов script и серверного контрола ScriptManager. Далее VS парсит файлы и пытается построить подсказку по коду. Если же нужно обновить подсказку, то можно нажать ctrl+shift+j.

Если же код пишется в .js файле, то файлы, которые надо анализировать для построения подсказки надо указать в специальном теге:

///<reference path="c:\scripts\jquery-1.5.1.js"/>


Создание Silverlight приложений для SharePoint. Часть 2.

Полгода прошло с тех пор как я опубликовал первую часть статьи. Как раз полгода назад произошло смещение приоритетов веб-разработки Microsoft  в сторону HTML5, и злые языки начали пророчить скорую смерть Silverlight. Тем не менее вышла пятая версия SL и, скорее всего, будет еще и шестая. Тем не менее фокус больше смещается в сторону HTML\JS, и по слухам в следующей версии SharePoint будет гораздо больше javascript и гораздо меньше SL.

Поэтому данная статья будет больше обзорной.

Варианты развертывания Silverlight приложений

Как обычно их три:

  1. В sandbox решении в виртуальную файловую систему sharepoint.
  2. В fulltrust решении в физическую файловую систему.
  3. Приложение на внешнем сервере, с использованием fluid application model.
Размещение Silverlight на портале.

Самый часто используемый способ – веб-часть silverlight. Её можно найти в категории Media. Также возможно создание своих веб-частей, которые отображают silverlight приложение, чтобы передать дополнительные параметры и\или сделать fallback. Но лучше такие веб-части не создавать, а воспользоваться расширением для visual studio. А в следующей версии visual studio такая веб-часть доступна “изкаропки”.

Еще один вариант – создание field control на silverlight. Пример можно посмотреть в статье на msdn.

Демо-приложение

Для демонстрации всех способов развертывания напишу простое приложение, при запуске оно будет выводить Title узла, на котором запущено приложение.

Сначала надо добавить в проект SL сборки Microsoft.SharePoint.Client.Silverlight  и Microsoft.SharePoint.Client.Silverlight.Runtime. Их можно найти в папке {SharePointRoot}\TEMPLATE\LAYOUTS\ClientBin.

Теперь можно написать немного кода:

var ctx = ClientContext.Current;
var web = ctx.Web;
ctx.Load(web, w => w.Title);


                
            


Поиск в приложениях SharePoint. Часть 1.

Одна из наиболее часто возникающих задач при разработке порталов на SharePoint  - создание веб-части , отображающей ближайшие дни рождения пользователей.

В SharePoint 2010 есть служба профилей пользователей, которая хранит данные о пользователях, в том числе дни рождения, в масштабах фермы. Для отображения списка пользователей можно использовать веб-часть "Основные результаты поиска людей". Но если разместить веб-часть на форму, то она не выводит результатов.

image

Чтобы отобразить результаты необходимо "Добавить текст в запрос".

image

Так как используется поиск надо заранее выполнить обход и в службе профилей должны быть записи.

 

Веб-часть отображения результатов поиска наследует DataFormWebPart, поэтому можно настроить отображение в виде xslt. Но для этого надо отключить отображение по-умолчанию.

image

XSL для отображения:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
  <table>
    <tr>
      <th>
        User name
      </th>
      <th>
        Account name
      </th>
    </tr>
    <xsl:apply-templates select="All_Results/Result"/>
  </table>
</xsl:template>
  <xsl:template match="Result">
    <tr>
      <td>
        <xsl:value-of select="preferredname"/>
      </td>
      <td>
        <xsl:value-of select="accountname"/>
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>


Миф о кастомизации страниц в SharePoint

Немного теории. В SharePoint есть виртуальная файловая система, которая содержится в контентной БД. Когда вы в farm solution помещаете в нее файл, с помощью модуля, то файл лежит на диске в {SharePointRoot}\TEMPLATE\Features, а контентной БД появляется ссылка на этот файл.

Таким образом экономится место в БД, ведь один и тот же файл может быть добавлен на несколько сайтов. Кроме того упрощается обновление – достаточно обновить файл на диске.

Такие файлы называются uncustomized, ghosted (в терминологии 2007 шарика) или просто некастомизироваными. Если же попробовать внести какое-либо изменение в файл в виртуальной файловой системе (!), то измененное состояние файла записывается в контентную БД и SharePoint перестает обращаться к диску за файлом. такие файлы называются customized, unghosted или кастомизированные.

Причем это относится не только к файлам в виртуальной ФС, но и к типам контента, шаблонам списков итд. Но об этом другой раз…

Миф

Кастомизированные страницы работают медленнее некастомизированных.

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

Я решил просто померить как изменяется скорость работы SharePoint от кастомизации страниц. Сделал простой веб-тест в Visual Studio, который обращается к странице по-умолчанию, а потом создал нагрузочный тест и замерял Page Response Time.

Вот график (кликабельно):

Центральный пик - сохранение кастомизированной страницы, слева - время ответда для некастомизированной старницы, справа - время ответа кастомизированной страницы. Среднее время ответа некастомизированной страницы – 1.7 сек, кастомизироанной – 1.9 сек. Разница около 10%. Если на странице будут “тяжелые” контролы, то разница станет еще менее заметной.

При кастомизации мастер страницы график еще интереснее:

Большой пик – кастомизация мастер-страницы. Справа пик поменьше – было сделано Revert To Definition для мастер-страницы. Получается результаты почти одинаковые, за исключением того, что для некастомизированного masterpage результаты гораздо менее стабильны.

Заключение

Использовать исключительно некастомизированные страницы имеет смысл только для hiload публичных сайтов. Хотя кто использует sharepoint для hiload сценариев???….



Октябрьская встреча Russian SharePoint User Group

Ссылка на анонс на сайте RUSUG: http://rusug.net/News/Lists/Posts/Post.aspx?ID=64

Один из докладов на встрече, про использование поиска в приложениях SharePoint, буду читать я. Чтобы больше удовлетворить интерес и потребности аудитории предлагаю выбрать интересующие темы из списка ниже:

  1. Настройка поиска SharePoint Server
  2. Out-of-box возможности поиска
  3. Кастомизация out-of-box функциональности
  4. Использование серверного API поиска
  5. Использование клиентского API поиска в sandboxed решениях
  6. Архитектура поиска SharePoint Server

Все темы в пределах одного доклада не смогу рассказать, но 3-4 из них вполне могу пройти достаточно подробно.

Пишите пожелания в комментах. Приходите на встречу. Но даже если вы не сможете прийти на встречу, то будет видеозапись докладов и ваши пожелания будут учтены.



Почему вам нужен SharePoint

Последнее время на различных конференциях я слышу один и тот же вопрос:

А зачем мне нужен SharePoint?

Вопрос банальный, частота его задавания связана с тем что очень много крупных и не очень компаний получают SharePoint вместе с различными пакетами программ Microsoft. Но вразумительных ответов на этот вопрос я пока не слышал.

Ниже “краткий” ответ, может быть вы найдете что-нибудь для себя.

  • Если вы руководитель или ИТ-директор компании более 5 человек и
    • Используете  MS Office
    • Отправляете документы по электронной почте
    • Использует расшаренные папки для хранения документов в электронном виде
    • У вас есть процессы согласования и утверждения документов
    • Храните данные в Excel или Access
    • Хотите создать базу знаний
    • Хотите развернуть helpdesk
    • Пользуетесь средствами средствами Microsoft BI
    • Хотите отображать данные из разных источников в одном месте
    • Хотите развернуть корпоративный портал для сотрудников

    если одно из вышеперечисленного верно, то вам однозначно нужен SharePoint. Он поможет вам создать единое хранилище документов и табличных данных с богатыми возможностями отображения и поиска. SharePoint позволяет создавать решения без среды разработки и написания кода. Продвинутые пользователи самостоятельно смогут создавать и улучшать решения в SharePoint.

  • Если вы менеджер проектов, то вам должны быть знакомы продукты MS Project и Project Server. Последний является надстройкой над SharePoint.
    Но даже без Projet Server вы можете:
    • Создавать отдельные сайты для проектов несколькими кликами мыши, где можно будет размещать и согласовывать документы
    • Хранить и отображать на портале списки задач из Microsoft Project
    • Отслеживать риски и проблемы
    • При необходимости вывести создать на портале SharePoint интерфейс к другим системам управления проектами
    • Получать сводку по вашим проектами
    • Получать отчеты и KPI на портале

  • Если вы архитектор или ведущий разработчик и разрабатываете корпоративный софт, то вам нужен SharePoint потому что:
    • он включает в себя возможности управления документами
    • он имеет надежную систему разграничения доступа
    • он интегрируется с MS Office
    • он позволяет искать по всему содержимому
    • он поддерживает длительные рабочие процессы, которые могут продолжаться больше чем время непрерывной работы серверов
    • он имеет модульный пользовательский интерфейс
    • он позволяет интегрироваться с другими системами
    • он поддерживает масштабируемость всех своих компонент
    • он почти весь функционал SharePoint поддается расширению и кастомизации
    • содержит систему установки и удаления приложений, гораздо проще, чем написание инсталляторов вручную

  • Если вы IT-специалист, то вам обязательно нужен SharePoint. Он вам позволит:
    • Собирать в одном месте данные из различных систем
    • Отображать таблицы, графики, отчеты, KPI на портале
    • Автоматизировать процессы процессы организации с помощью простых инструментов
    • Размещать веб-контент не имея навыков веб-разработки
    • Управлять множеством сервисов со сложной топологией с помощью простого графического интерфейса
    • Заскриптовать любые действия с помощью PowerShell

  • Если вы рядовой .NET разработчик, то вы сможете в SharePoint:
    • Применить уже имеющиеся навыки
      • для разработки интерфейса
      • для создания решений по интеграции с другими системами
      • для создания рабочих процессов
    • Изучив платформу более детально вы сможете создавать любые решения и превратитесь из рядового разработчика в высокооплачиваемого специалиста :)

  • Если вы веб-разработчик, то ваши навыки будут очень востребованы в среде SharePoint
    • для брендинга портала, это сейчас очень востребованная тема
    • для разработки макетов веб-страниц для размещения контента
      (html + css + js)
    • для создания представлений данных и результатов поиска
      (xslt + html + css + js)
    • для приложений на javascript или silverlight, большая часть функциональности SharePoint доступна на клиентской стороне

 

Несмотря на богатые возможности примеров успешных внедрений не так много, как хотелось бы. Это связано с тем что платформа SharePoint сложна, а специалистов не хватает. По большей части не хватает именно разработчиков, которые хорошо владеют функционалом и могут собрать из него решение.

Если у вас будут возникать вопросы по SharePoint , то присоединяйтесь с сообществу http://area51.stackexchange.com/proposals/35899/sharepoint-in-russian, поддержите его развитие и вы сможете получать много полезной информации.



Решение задач. Задача таймера, совсем конец.

Посты в этой серии:

  1. Список задач для проверки навыков.
  2. Создание задачи таймера.
  3. Использование подходящих классов.
  4. Передача команд задаче таймера.
  5. Взаимодействие веб-фронтэнда с задачами таймера (этот пост).

В прошлом посте был показан способ создать worker, который будет получать сообщения от frontend и обрабатывать их.

Теперь необходимо придумать как оправлять эти сообщения. В 2010 есть почти универсальный способ для размещения функционала – Ribbon. Даже если у вас возникает непреодолимое желание сделать ссылку\кнопку\пункт меню в другом месте, то скорее всего для целей usability надо будет повторить его в ribbon.

Для того чтобы добавить кнопку в ribbon надо создать custom action, я для этого использую cks:dev. Руководство по расширению риббона можно найти как на MSDN, так и в блогах глубоко уважаемых людей (надеюсь меня не забанят за такое количество ссылок).

Мой код получился такой:

<CustomAction Id="CleanupLibraryButton"
              Title="Cleanup"
              RegistrationType="List"
              RegistrationId="101"
              Location="CommandUI.Ribbon">
  <CommandUIExtension>
    <CommandUIDefinitions>
      <CommandUIDefinition Location="Ribbon.Library.Settings.Controls._children">
        <Button Id="Ribbon.Library.Settings.Cleanup"
                Command="CleanupLibraryCommand"
                TemplateAlias="o2"
                LabelText="Cleanup"
                Sequence="100"
                Image16by16="/_layouts/images/warning16by16.gif"
                Image32by32="/_layouts/images/CRIT_32.GIF"                   
                />
      </CommandUIDefinition>
    </CommandUIDefinitions>
    <CommandUIHandlers>
      <CommandUIHandler Command="CleanupLibraryCommand" 
                        CommandAction="???"/>
    </CommandUIHandlers>
  </CommandUIExtension>
</CustomAction>


Решение задачи. Задача таймера, почти конец.

Посты в этой серии:

  1. Список задач для проверки навыков.
  2. Создание задачи таймера.
  3. Использование подходящих классов.
  4. Передача команд задаче таймера (этот пост).
  5. Взаимодействие веб-фронтэнда с задачами таймера.

Задачи таймера сами по себе очень важны для многих решений, но не менее важно взаимодействие задач таймера с другими частями решения.

Например, задача таймера, которая выполняет очистку папок, требует большого количества ресурсов для работы, фактически просмотр всех баз контента для того чтобы удалить папки. Даже если надо удалить ровно одну папку, то задача таймера все равно будет бегать по всей контентной базе данных. Такое поведение крайне расточительно.

Надо как-то ограничить задачу таймера чтобы она бегала только по тем сайтам где разрешит администратор.

Проще всего этого добиться создав фичу уровня Web, которая выставляет свойства узла при активации и модифицировать задачу таймера, чтобы она проверяла свойство.

Код Feature Receiver

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    SetCleanupFlag(properties, true);
}


                
            


Решение задачи. Задача таймера, продолжение.

  1. Список задач для проверки навыков.
  2. Создание задачи таймера.
  3. Использование подходящих классов (этот пост).
  4. Передача команд задаче таймера.
  5. Взаимодействие веб-фронтэнда с задачами таймера.

В прошлый раз я писал о том как создать задачу таймера в SharePoint. Такой код писать не нужно. Надеюсь никто не успел скопипастить код к себе в проект.

В SharePoint 2010 основной класс для создания задач таймера – SPPausableJobDefinition. В отличии от обычного SPJobDefinition, как вы можете догадаться из названия, SPPausableJobDefinition можно останавливать.

Чтобы создать приостанавливаемую задачу таймера надо переопределить метод Execute с параметром SPJobState. Объект класса SPJobState содержат как свойства, говорящие о том что задача должна остановиться, так и методы сохранения текущего состояния задачи таймера для продолжения работы.

С одной стороны возможность приостанавливать выполнение задачи таймера ведет только к усложнению кода, но нету необходимости писать код, он уже есть в сборке Microsoft.SharePoint.

Класс, который больше всего подходит к нашей задаче – SPAllSitesJobDefinition. Задачи таймера, наследующиеся от этого класса должны переопределить только один метод ProcessSite.

public class TimerJob : SPAllSitesJobDefinition
{
    public TimerJob()
        : base()
    {


                
            


Решение задачи. Задача таймера.

  1. Список задач для проверки навыков.
  2. Создание задачи таймера (этот пост).
  3. Использование подходящих классов.
  4. Передача команд задаче таймера.
  5. Взаимодействие веб-фронтэнда с задачами таймера.

Ранее я приводил список задач для проверки навыков программирования для SharePoint. Сегодня напишу о решении четвертой задачи про задачу таймера для очистки библиотек документов от пустых папок.

Задача

Создать задачу таймера (Timer Job), которая буде находить в библиотеках документов пустые папки, в которых нет файлов и которые содержат пустые папки, и удалять их.

Класс задачи таймера

Чтобы создать задачу таймера необходимо создать класс, унаследованный от Microsoft.SharePoint.Administration.SPJobDefinition. Этот класс недоступен в sandbox, поэтому вам нужен farm solution.

В этом классе необходимо переопределить метод Execute и конструктор с параметрами.

public TimerJob(SPWebApplication webApp)
    : base(Constants.TimerJobName, webApp, null,
           SPJobLockType.ContentDatabase)
{
    this.Title = "Folder cleanup job";
}


Решение задач. Соединенные веб-части, продолжение.

В прошлый раз я рассказывал как сделать простые соединенные веб-части. Сегодня буду рассказывать как улучшить решение и сделать его более полезным в реальной жизни.

План действий

  1. Фильтрация в SPGridView
  2. Оптимизация передачи данных между веб-частями
  3. Добавление параметров для веб-частей
  4. Асинхронная загрузка дерева
  5. Bin deployment


Фильтрация в SPGridView

Разрабатывая UI на SharePoint мы имеем всю мощь библиотеки контролов ASP.NET, об этом не стоит забывать. Вместо того чтобы реализовывать функционал который уже есть лучше потратить время на изучение существующих возможностей.

Например можно перехватывать события SPGridView для обработки фильтрации, а можно использовать существующий инструментарий контролов Data Source для этих целей.

Подробно описано в статье, здесь приведу вкратце код для достижения цели.

Создание дочерних элементов веб-части:

this.ds = new ObjectDataSource(typeof(GridTableConsumer).AssemblyQualifiedName, "SelectData")
    {
        ID = "gridDS",
        EnableCaching = false
    };
this.ds.ObjectCreating += (sender, e) => e.ObjectInstance = this;
this.Controls.Add(this.ds);


                
            


Решение задач. Соединенные веб-части.

Ранее я приводил список задач для проверки навыков программирования для SharePoint. Сегодня напишу о решении второй задачи про соединенные веб-части.

Задача

  1. Создать веб-часть дерева организаций (подразделений)
  2. Сделать её провайдером IWebPartTable
  3. При выборе узла дерева веб-часть должна отправлять   профили пользователей в организации
  4. Создать веб-часть потребитель IWebPartTable с помощью SPGridView

Подготовка

Разработка SharePoint полна тонких моментов, поэтому критически необходимо внимательно читать документацию на MSDN и то что пишут в блогах до написания кода.

Для решения задачи с соединенными веб частями понадобятся следующие ссылки:

  1. Жизненный цикл веб-частей в SharePoint. Не уверен что сведения в этой статье точные, но они достаточно полные (помните правило: если о чем-то пишут, то не значит что оно так и работает).
  2. Описание IWebPartTable. В конце статьи есть пример реализации, все довольно просто.
  3. Описание SPGridView: часть 1, часть 2, часть 3, часть 4. Очень хорошая серия если будете использовать SPGridView в своих проектах.
  4. Классы OrganizationProfileManager и UserProfileManager для работы с профилями.

Создание проекта

Выбираем Empty SharePoint Project, создаем его как Farm Solution

image

Добавляем две веб-части

image

По-умолчанию Visual Studio 2010 прописывает в .webpart файлах имена классов. это крайне неудобно, так как необходимо вручную править .webpart файлы при переименовании классов\изменении пространства имен.

Используя сведения отсюда, добавляем атрибуты классам веб-частей и изменяем .webpart файлы.

image

image

Создание дерева организаций

Для вывода дерева будем использовать контрол TreeView.

private TreeView tree;


                
            


Создание Silverlight приложений для SharePoint. Часть 1.

Зачем?

Как ни странно, но этот вопрос обычно не задают. Многие хотят получить интерактивные интерфейсы SharePoint, но при этом не хотят изучать особенности объектной модели и пользоваться знакомыми инструментами.

Если все же подумать, то причины для создания Silverlight приложения могу быть следующие:

  1. Необходимость создания высокоинтерактивого интерфейса в SharePoint.
    Стандартный интерфейс sharepoint хоть построен с помощью ajax, но все же не является настолько отзывчивым, насколько этого хотят пользователи.
  2. Необходимость производить тяжелые расчеты в окружении с ограниченным доверием.
    Например при развертывании приложений в Office365 вы ограничены sandbox для серверной объектной модели. Ресурсы, потребленные серверным кодом, будут считаться и ваше решение может быть отключено. Кроме того существует тайм-аут в 30 секунда на выполнение кода в sandbox. Silverlight позволяет преодолеть эти ограничения, переложив вычисления на клиентский компьютер.
  3. Расширение возможностей пользовательского интерфейса SharePoint.
    Один из примеров таких расширений – возможность использовать drag-and-drop файлов с локального компьютера в библиотеку документов (ссылка на статью).
  4. Создание бизнес-приложения, которое в дальнейшем может быть установлено для автономной работы (out-of-browser).
  5. Hi-end media-сценарий. Без Silverlight пока что невозможен smooth streaming.

В указанных выше случаях Silverlight – практически единственная возможность решить задачу.
Кроме того Silverlight может использоваться для преодоления ограничений sandbox, связанных с вызовом внешних сервисов, для создания графических элементов управления, итд. Но все это с таким же успехом может быть реализовано с помощью HTML5\javascript.

Почему не стоит использовать Silverlight

Приложения на Silverlight имеют достаточно много ограничений чтобы задуматься об их использовании.

  1. Мобильные устройства. На мобильных устройствах Silverlight нет, если ваше приложение не предусматривает fallback к обычному html+js, то вы потеряете функционал на мобильных устройствах.
  2. Брендинг. Чтобы приложение Silvelight выглядело как остальной портал необходимо приложить довольно много усилий.
  3. UX. Несмотря на богатую графику, простая операция вроде “выделить кусок текста и скопировать” его в Silverlight доступна только в специальных контролах.
  4. Время загрузки. Silverlight приложения загружаются после отрисовки страницы, это всегда заметно глазом человека.

Если вы все таки собираетесь использовать Silverlight в SharePoint

Посмотрите как сам SharePoint использует Silverlight. Меню создания сайта\списка сделано на Silverlight, это скорее неудачное решение. Данное меню сильно таращит на русском языке. При возникновении ошибки в процессе создания элемента появляется popup с Corellation ID, но этот Corellation ID оттуда нельзя скопировать.
Другой, гораздо более удачный, пример – множественная загрузка файлов в библиотеку. Это почти незаметный компонент, который тем не менее может сильно упростить жизнь пользователям.
Еще один хороший пример использования Silverligth в SharePoint – инструмент, называемый decomposition tree, из Performane Point Services. С его помощью можно формировать декомпозицию мер по измерениями в кубе SSAS.

Посмотрите также проект SharePoint People Search Pivot Viewer WebPart. Очень показательно какие возможности имеет Silverlight для визуализации данных SharePoint.

Чтобы научиться создавать приложения на Silverlight для SharePoint можно пройти учебный курс.



Задачи для проверки навыков разработки SharePoint

Когда я читаю курс 10175, то из положенных 5 дней лекции удается уложить в 4, а в последний день обучающиеся выполняют лабораторную работу, чтобы проверить полученные знания и навыки разработки приложений.

Ниже приведены 4 задачи, из  которых обучающиеся в парах выполняют одну. Звездочками отмечены задачи, которые не рассматриваются в курсе и требуют самостоятельного изучения.

  1. Создать систему резервирования ресурсов
    • Создать список ресурсов
    • Создать список (стандартный шаблон списка “Календарь”) со ссылкой на список ресурсов
    • Создать обработчик события добавления и изменения, который проверяет непересекаемость интервалов резервирования для ресурса и отменяет действие в случае пересечения
    • * Создать веб-часть, отображающую свободные  ресурсы в заданном интервале времени
    • Код должен работать в sandbox
  2. Создать соединенные веб-части
    • Создать веб-часть отображающую дерево организаций (подразделений)
    • Сделать её провайдером IWebPartTable
      • При выборе узла дерева веб-часть должна отправлять   профили пользователей в организации
    • Создать веб-часть потребитель IWebPartTable с помощью SPGridView
    • * Реализовать поддержку фильтрации и сортировки в SPGridView как в представлениях SharePoint
  3. Создать рабочий процесс обработки инцидентов
    • Создать список инцидентов (стандартный шаблон списка "”Списко Инцидентов”)
    • Создать State Machine Worflow с 3 состояниями: Открыт, Закрыт, Проверен
    • В каждом состоянии необходимо назначать пользователю (для простоты администратору) задачу, после выполнения задачи удалять её.
    • После после исполнения задачи процесс должен изменять состояние инцидента
    • * Сделать график времени закрытия инцидентов по типам с помощью Performace Point Services
  4. Создать задачу таймера очистки библиотек документов
    • Задача должна находить и удалять пустые папки в библиотеках документов   
    • * Доработать задачу таймера чтобы она работала только на заданных узлах (SPWeb)
    • * Создать Custom Action в Ribbon и SiteMenu для того чтобы вызвать задачу таймера.

ИМХО хороший программист SharePoint должен уметь выполнить любую задачу в течение дня.

Ваши комментарии?



SharePoint Administrator Roadmap

Снова по просьбам читателей

  1. Для изучения администрирования SharePoint понадобятся базовые знания об администрировании следующих компонент и приложений:
    1. Active Directory Domain Services
    2. SQL Server 2008
    3. IIS Weberver
  2. Для начала просмотреть видеокурс Getting Started for IT Pros.
  3. Затем курс Advanced IT Professional Training. Обязательно выполните лабораторки в этом курсе.
  4. Далее прочитайте цикл статей про развертывание SharePoint в организации.
  5. Администраторы обычно выполняют  функции Power Users, занимаются небольшими кастомизациями и обучением пользователей. Поэтому крайне необходимо изучать все материалы на сайте http://office.microsoft.com/ru-ru/training/.
  6. Если вы хотите качественно настроить поиск SharePoint, то вам может пригодиться видеокурс Enterprise Search IT professional training. Обязательно выполняйте лабораторки.
  7. Справку и различные гайды по интересующим вас аспектами SharePoint вы сможете найти в Resource Centers.
  8. Для повышения квалификации выполняйте лабораторные работы. Они отнимают немного времени и позволяют изучить различные аспекты с которыми вы (пока) не столкнулись в работе.
  9. SharePoint активно использует PowerShell для администрирования. Изучайте PowerShell, это поможет вам решать задачи, которые требуют программирования.
  10. Ответы почти на все вопросы можно найти на TechNet. Зачастую достаточно пошагово выполнить руководство чтобы все заработало как надо.


Развертывание решений SharePoint с помощью PowerShell

После прочтения кучи книг, статей и просмотра видео, обойдя все подводные камни, и сделав наконец свое решение на SharePoint у вас появляется вопрос: “а как его запустить у заказчика?” Visual Studio предательски сама активирует фичи решения по F5 и деактивирует при завершении отладки. А как тоже сделать у заказчика? А если у вас доступа на машину заказчика нет?

Для начала стоит подробнее рассмотреть что же требуется для развертывания вашего решения. Обычно развертывание состоит из нескольких шагов:

  1. Добавление WSP-решений уровня фермы
  2. Добавление sandboxed решений
  3. Активация фич
  4. Выполнение дополнительных действий

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

Вроде все просто. Вооружившись справочником по командам PowerShell  для SharePoint попробуем написать скрипт

Add-SPSolution -LiteralPath "SomePath\MySolution.wsp"
Install-SPSolution -Identity "mysolution.wsp" -GACDeployment
Enable-SPFeature MyFeature -Url http://localhost/

Сразу куча проблем:

  1. Работает только из SharePoint Management Shell
  2. Add-SPSolution  не понимает относительных путей
  3. На localhost не будет нужного сайта или надо будет разворачивать в другое место
  4. Sandboxed решения так добавить не получится

Чтобы не заставлять пользователя запускать Management Shell можно написать в начале

Add-PSSnapin Microsoft.SharePoint.Powershell

Но после этого появляется ошибка при запуске из Management shell…

Чтобы обойти проблему нужно проверять загружено ли расширение

if(!(Get-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction:SilentlyContinue))
{
    Add-PSSnapin Microsoft.SharePoint.Powershell
}

Вместо hardcoded параметра сайта можно запрашивать параметр в скрипте с помощью оператора param.  А вот чтобы получить текущий путь скрипта надо использовать хак.

Второй вариант скрипта:

param($siteUrl= $(Read-Host "siteUrl"))


                
            


SharePoint 2010 и OData

Наверное все знают что SharePoint 2010 имеет OData-сервис, к которому можно обратиться по адресу http://{siteUrl}/_vti_bin/listdata.svc. Также SharePoint имеет очень мощную службу бизнес-данных (Business Connectivity Services), с помощью которой можно обращаться к различным источникам данных. К сожалению OData-сервисы не входят в число этих источников.

Чтобы исправить это досадное упущение, был создан Custom Connector для BCS, который умеет работать с OData-сервисами. А также был создан генератор модели подключения к внешним данными, чтобы упростить подключение OData источников к BCS.

Найти все это можно по адресу http://vega-soft.com/spodata/.

Фичи, реализованные на данный момент:

  1. Генератор модели
  2. CRUD-операции с данными
  3. BCS фильтры: Limit, Paging, Comparison, LastId

Фичи, планирующиеся в ближайшее время:

  1. Ассоциации (связи между сущностями)
  2. Поддержка ad-hoc запросов
  3. Аутентификация
  4. Улучшенный генератор модели

PS. Для тех кто не в курсе что такое OData – рекомендую детально изучить сайт http://www.odata.org/.



SharePoint Developer Roadmap

По просьбам читателей

  1. SharePoint это в первую очередь ASP.NET приложение, если не владеете им, то начать можно отсюда: http://www.asp.net/web-forms.
  2. Далее Get Started: http://msdn.microsoft.com/en-US/sharepoint/ee513147.aspx, обязательно выполните лабораторные работы.
  3. Затем сразу Advanced training: http://msdn.microsoft.com/en-US/sharepoint/ff420377.aspx, обязательно выполните лабораторные работы.
  4. В дальнейшем ответы на вопросы по использованию отдельных модулей шарика можно найти в Resource Centers: http://msdn.microsoft.com/en-US/sharepoint/bb964529.aspx.
  5. Далее обязательно прочитать книгу Real World SharePoint 2010: Indispensable Experiences from 22 MVPs, узнаете много нового
  6. Если будете заниматься брендингом (созданием уникального внешнего вида) SharePoint, то вам также понадобится книга Professional SharePoint 2010 Branding and User Interface Design.
  7. Далее обязательно изучите SharePoint Guidance 2010, причем как примеры кода (он там, чуть более чем образцовый), так и подходы к разработке. Кстати там тоже есть лабораторные работы, которые также надо выполнить.
  8. SharePoint это не только ценный мех серверная платформа, но и мощная клиентская часть в виде Office 2010. Для изучения Office и его интеграции с SharePoint можно посмотреть онлайн курс: http://msdn.microsoft.com/en-us/gg605831, и снова обязательно выполнить все лабораторки.
  9. Из того же комплекта обучающих курсов стоит пройти курсы по Office365, SharePoint and Silverlight.
  10. Со временем вы поймете что 90% задач в SharePoint\Office можно решить с помощью существующих средств. Чтобы в совершенстве овладеть всеми этими средствами надо внимательно изучить контент на сайте http://office.microsoft.com/ru-ru/training/

Чтобы ускорить процесс можете прослушать курсы, которые я читаю.



Об обработчиках событий элементов списка, часть 2

В прошлом посте я писал о подводных камнях при создании обработчиков элементов списка. Теперь хочу рассмотреть реальный сценарий создания такого обработчика.

Наиболее часто программисты SharePoint сталкиваются с необходимостью реализовать field-level security, так как встроенных механизмов в SharePoint нет (зато в Dynamics CRM есть, если что).  Можно написать кастомные формы, которые на уровне интерфейса блокируют возможности поправить значения элементов, но учитывая богатые клиентские возможности SharePoint 2010 такие ограничения легко обойти.

Поэтому необходимо написать код, который в который при событии Updating сможет определить изменилось поле или нет. Ну и желательно чтобы код был универсальным и работал для любого списка и библиотеки.

Первое приближение:

public static bool IsFieldChanged(this SPItemEventProperties properties, 
                                       SPField field)
{
    var after = (string)properties.AfterProperties[field.InternalName];            
    var before = Convert.ToString(properties.ListItem[field.Id]);
    
    return after != before;
}

Этот код обрабатывает довольно малое число use cases:

  1. AfterProperties может быть null если свойство не менялось (хотя при отправке формы в AfterProperties  попадают все поля)
  2. AfterProperties содержит пустую строку если значения нет, SPListItem может при этом возвращать как пустую строку, так и null

Второе приближение:

public static bool IsFieldChanged(this SPItemEventProperties properties, SPField field)
{
    var after = (string)properties.AfterProperties[field.InternalName];            
    var before = Convert.ToString(properties.ListItem[field.Id]);
    


                
            


Об обработчиках событий элементов списка

Обработчики событий элементов списка  это классы, унаследованные от SPItemEventReceiver. В классе содержится много методов, почти все они делятся на две группы: Pre-события – методы, оканчивающиеся на -ing, и Post-события – методы, оканчивающиеся на -ed. Все события принимают один аргумент экземпляр класса SPItemEventProperties.

Это теоретический минимум, который необходимо знать для начала.

Коварные AfterProperties и BeforeProperties

Класс SPItemEventProperties содержит пару свойств: AfterProperties и BeforeProperties. На первый взгляд очень хорошие свойства, которые позволяют с небольшими усилиями реализовать множество сценариев. Но на деле все не так…

  1. Для начала необходимо запомнить, а потом распечатать и повесить на стену, на холодильник, да доску и на все остальные поверхности следующие таблицы:
    Список BeforeProperties AfterProperties properties.ListItem
    ItemAdding Пусто Новые значения null
    ItemAdded Пусто Новые значения Новые значения
    ItemUpdating Пусто Новые значения Старые значения
    ItemUpdated Пусто Новые значения Новые значения
    ItemDeleting Пусто Пусто Старые значения
    ItemDeleted Пусто Пусто null

    Библиотека BeforeProperties AfterProperties properties.ListItem
    ItemAdding Пусто Пусто null
    ItemAdded Пусто Пусто Новые значения
    ItemUpdating Старые значения Новые значения Старые значения
    ItemUpdated Старые значения Новые значения Новые значения
    ItemDeleting Пусто Пусто Старые значения
    ItemDeleted Пусто Пусто null

    Поведение списков и библиотек документов разное и отличается от предполагаемого.
    Как видите из таблиц выше, BeforeProperties почти бесполезное свойство.
  2. AfterProperties и BeforeProperties содержат свойство ChangedProperties. Это свойство показывает измененные поля в самой коллекции, а не в элементе.
  3. Свойство-индексатор AfterProperties и BeforeProperties принимает Internal Name поля, а не Display Name как в properties.ListItem.
  4. AfterProperties и BeforeProperties поддерживают нетипизированный IEnumerable, но нигде в документации не указано какого типа возвращается перечисление. Опыты показывают что возвращается DictionaryEntry.
  5. AfterProperties и BeforeProperties возвращают все значения в виде строк. Кроме того для boolean типа поля может быт возвращено "-1" в качестве значения, а строки возвращаются в универсальном формате и при парсинге автоматически переводятся в текущую локаль (+3 часа обычно получается).
  6. При изменении элемента списка в коде в AfterProperties попадают только измененные значения, а при сохранении формы – все значения формы.
  7. При сохранении формы с RichText полем в AfterProperties попадает HTML со всеми заглавными буквами в названиях тегов.

Отмена действия

Pre-события позволяют отменить действие. Для этого необходимо в properties.Cancel присвоить true, присвоить необходимые значения свойствам properties.Status и properties.ErrorMessage. Но и тут есть особенности:

  1. Если вы собираетесь отменить действие, то не вызывайте базовую реализацию метода-обработчика. Иначе отмена не произойдет.
  2. Если вы поставите статус CancelWithError, то будет выкинуто стандартное исключение, которое в режиме отладки отображается желтым экраном смерти.
  3. Если хотите показать свое сообщение об ошибке, то сделайте CancelWithRedirect, но учтите что в таком случае управление не вернется к вызывающему коду.
  4. Если необходимо выполнение разных способов отмены, то анализируйте SPContext и его свойства FormContext и ViewContext.
  5. Отмена работает всегда, для любой учетной записи, в том числе системной. Желательно позволять выполнять действие (не отменять его) администратору коллекции сайтов и учетной записи "SHAREPOINT\system".

Конкурентное выполнение обработчиков событий

В этом посте описан пайплайн обработки событий, картинка ниже кратко его иллюстрирует.

Как видно обработчики Post-событий могут запускаться параллельно. Если будут параллельно запускаться несколько обработчиков, изменяющих сам элемент, то может появиться состояние гонки. Класс SPListItem снабжен механизмом так называемой “оптимистичной конкуренции”. В случая если другой потом успел поменять значение в базе между моментом считывания и записью данных, то выпадет исключение. Но исключения в пост-обработчиках не очень эффективны, так как нет возможности как-либо сигнализировать об ошибке, если только это не синхронный обработчик.

  1. По возможности не изменяйте элемент списка из асинхронного пост-обработчика.
  2. Перехватывайте SPListDataValidationException. Если поймали такое исключение, то выполните properties.InvalidateListItem, а потом снова код обновления элемента.
  3. Используйте следующий блок кода в пост-обработчиках, чтобы не вызвать их циклического запуска
    try
    {
        this.EventFiringEnabled = false;
        //...здесь вызов Update...
    }
    finally
    {
        this.EventFiringEnabled = true;
    }
  4. Также можно использовать SystemUpdate, чтобы не вызывать обработчики событий и не менять время последнего изменения элемента.

К сожалению это далеко не все грабли, которые встречаются при обработке событий. С прочими граблями можно ознакомиться тут:http://msdn.microsoft.com/en-us/library/aa979520.aspx


SharePoint и Url форм

Постоянно вижу вопрос на форумах: “Как в SPD сделать ссылку на элемент списка?”

Ответ: Используйте listform.aspx

{webUrl}/_layouts/listform.aspx?ListId={ListId}
&PageType={PageType}
&ContentTypeId={CTId}
&ID={ItemId}


Начинающим админам SharePoint

Что нужно почитать чтобы правильно развернуть ферму в вашей организации.

Подготовка

https://www.nothingbutsharepoint.com/sites/itpro/Articles/Pages/life-on-the-farm-intro.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Articles/Pages/life-on-the-farm-prep-work-1.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Articles/Pages/life-on-the-farm-prep-work-2.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Articles/Pages/life-on-the-farm-prep-work-3.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Articles/Pages/life-on-the-farm-prep-work-4.aspx

Установка


https://www.nothingbutsharepoint.com/sites/itpro/Articles/Pages/life-on-the-farm-installation.aspx

Настройка


https://www.nothingbutsharepoint.com/sites/itpro/Pages/life-on-the-farm-post-install-configure-part-1.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Articles/Pages/life-on-the-farm-post-install-configure-part-2.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Articles/Pages/life-on-the-farm-post-install-part-3.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Pages/Life-on-the-Farm-SP2010-Configuration---Post-Install-Setup-Part-4.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Articles/Pages/life-on-the-farm-post-install-configure-part-5.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Articles/Pages/life-on-the-farm-post-install-configure-part-6.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Pages/life-on-the-farm-post-install-configure-part-7.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Pages/life-on-the-farm-post-install-configure-part-8.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Pages/life-on-the-farm-post-install-configure-part-9.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Articles/Pages/life-on-the-farm-post-install-configure-part-10.aspx
https://www.nothingbutsharepoint.com/sites/itpro/Pages/life-on-the-farm-post-install-configure-part-11.aspx



Процессинг в SharePoint

SharePoint обладает всеми свойствами распределенной БД. Разные семейства сайтов могут находиться в разных контентных базах данных. Разные контентные БД могут находиться на разных серверах. Запросы к структурированным данным работают небыстро и самый эффективный способ – обращение по ключу. Часто используется поиск для нахождения нужных данных во всей базе.

Для того чтобы обрабатывать много данных в базах SharePoint  используются задачи таймера, которые выполняют запросы к БД и обрабатывают полученные данные. Но не для всех случаев запросы можно выполнить эффективно.

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

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

Другой подход – создавать процесс с ожиданием до заданного времени. Но процессы тяжеловесны и их использование отражается на интерфейсе пользователя. Кроме того есть ограничения на количество работающих процессов в SharePoint. Тоже плохо масштабируется

Нам нужен способ позволяющий передать данные из фронтэнда (веб-приложения) в бекэнд (службу таймера). В распределенных приложениях для этого используются очереди. Но беглый просмотр API шарепоинта говорит нам что очередей нет, а в SharePoint 2010 нельзя из контекста веб-приложения изменить свойства объектов, унаследованных от SPPersitedObject (подробнее тут), и мы не можем записать что-либо в сам объект задачи таймера или в любой дочерний.

Более детальный просмотр Server OM показал одну маленькую функцию SPSite.AddWorkItem, которая добавляет куда-то workitem, и класс SPWorkItemJobDefinition наследуясь от которого можно определить задачу таймера, разгребающую эти workitem. Вот где прятались очереди в sharepoint.

Таким образом мы можем в обработчике события на изменение элемента ставить задачу в очередь, указывая дату и время когда она должна быть обработана, а обо всем остальном позаботятся внутренние механизмы.

Удивляет отсутствие толковой документации и примеров использования этого метода. Похоже что это внутренний механизм, который частично торчит наружу, но далеко не до всех деталей, которые используют процессы и алерты (да-да, они именно такой метод используют) можно добраться. Тем не менее то что доступно вполне можно использовать для своих целей.



DataSheet View и Office 2010 x64

Если кто-либо имел счастье работать с SharePoint c помощью Office 2010 64-битной редакции, то обратил внимание что не работает DataSheet View при просмотре таблиц. Выпадает сообщение об отсутствии ActiveX компонент.

Проблема решаема: http://support.microsoft.com/kb/2266203



Группировка элементов в XSLT 1.0

По счастливой случайности я активно занимаюсь разработкой на SharePoint 2010. Для отображения данных в нем использует XSTL 1.0 в котором отсутствует оператор for-each-group. Вот чтобы сделать группировку надо написать такой код:

<xsl:stylesheet  version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="имя-индекса" match="элементы-для-друппировки" use="ключ-для-группировки" />
    <xsl:template>
        <xsl:for-each 
            select="элементы-для-друппировки[count(. | key('имя-индекса', ключ-для-группировки)[1]) = 1]">
            <!--преобразование для группы-->
         <xsl:for-each select="key('имя-индекса', ключ-для-группировки)">
                <!--преобразование для элементов группы-->
         </xsl:for-each>
            <!--преобразование для группы-->
        </xsl:for-each>        
    </xsl:template>    
</xsl:stylesheet>