вторник, 29 мая 2012 г.

Улучшения для разработчиков SharePoint

Хочу, наконец-то, поделиться своими небольшими улучшениями для разработчиков (в основном) SharePoint.

 

Улучшения касаются возможности быстро выполнить некоторые действия, которые иногда приходится нам делать – добавить библиотеку в GAC (и выполнить IISReset), установить решение – двойным кликом по соответствующему файлу:

 

image

image

 

По установке: решение состоит из файлов реестра, bat-файлы (пришлось использовать для комплексных действий) необходимо размещать в папке “C:\\Program Files\Microsoft SDKs\Windows\v7.0A\Bin\” (или подправить соответствующим образом файлы реестра).

 

Скачать можно тут.

суббота, 19 мая 2012 г.

Получение данных об изменениях на сайте - использование SPChangeQuery

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

Для осуществления запроса вызывается метод .GetChanges() объекта SPSite, SPWeb, SPList или SPContentDatabase.

 

Рассмотрим возможные отслеживаемые действия:

var query = new SPChangeQuery(false, false)
                {
                    Add = true, // Добавление объекта
                    Delete = true, // Удаление объекта
                    Update = true, // Обновление объекта
                    SystemUpdate = true, // Системное обновление элемента
                    GroupMembershipAdd = true, // Добавление пользователя в группу
                    GroupMembershipDelete = true, // Добавление пользователя в группу
                    Move = true, // Перемещение объекта
                    Rename = true, // Переименование объекта
                    Restore = true, //Восстановление объекта из корзины или архивной копии
                    RoleAssignmentAdd = true, // Назначение роли пользователю или группе
                    RoleAssignmentDelete = true, // Удаление роли
                    RoleDefinitionAdd = true, // Назначение разрешений роли
                    RoleDefinitionDelete = true, // Удаление разрешений роли
                    RoleDefinitionUpdate = true, // Обновление разрешений роли
                };

и возможные отслеживаемые объекты:

var query = new SPChangeQuery(false, false)
                {
                    Alert = true, // Оповещения
                    ContentType = true, // Типы содержимого
                    Field = true, // Поля списка
                    File = true, // Файлы
                    Folder = true, // Папки
                    Group = true, // Группы
                    Item = true, // Элементы списков
                    List = true, // Списки
                    Navigation = true, // Элементы навигации
                    SecurityPolicy = true, // Политики безопасности
                    Site = true, // Коллекция сайтов
                    User = true, // Пользователи
                    View = true, // Представления списков
                    Web = true, // Сайт
                };

Также позволяет задавать начальную (ChangeTokenStart) или конечную (ChangeTokenEnd) дату возвращаемых изменений.

 

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

using (var site = new SPSite("http://site/"))
{
    using (var web = site.OpenWeb())
    {
        var list = web.Lists["TestList"];
        var timeZone = web.RegionalSettings.TimeZone;

        var query = new SPChangeQuery(false, false)
                        {
                            FetchLimit = 500, // Limit
                            Item = true, // Object type
                            Add = true, // Change type
                            Delete = true, // Change type
                            Update = true, // Change type
                            ChangeTokenStart = new SPChangeToken(SPChangeCollection.CollectionScope.List, list.ID, new DateTime(2012, 05, 11)) //From date
                        };

        Console.WriteLine("{0,-20}{1, -10}{2}", "Title/ID", "Action", "Time");

        while (true)
        {
            var changes = list.GetChanges(query);

            foreach (var change in changes.OfType<SPChangeItem>())
            {
                string itemTitle;
                try
                {
                    itemTitle = "Item Title: " + list.Items.GetItemById(change.Id).Title;
                }
                catch (Exception)
                {
                    itemTitle = "Item Id: " + change.Id;
                }

                Console.WriteLine("{0,-20}{1, -10}{2}", itemTitle, change.ChangeType, timeZone.UTCToLocalTime(change.Time));
            }

            // Go to next batch or break
            if (changes.Count < query.FetchLimit)
                break;
            query.ChangeTokenStart = changes.LastChangeToken;
        }
    }
}

 

Результат работы программы (консольное приложение):

image

понедельник, 14 мая 2012 г.

Upload Control – Работа с элементом управления загрузки множества файлов

Сразу покажу скриншоты, о чём идёт речь:
image
image
Позволяет загружать файлы в папку или библиотеку документов на веб-сервере. В работе не сложен, но есть много нюансов.
Итак, исходный код.
<script type="text/jscript">
    function DocumentUpload() {
        var uploadCtl = document.getElementById("idUploadCtl");
        uploadCtl.MultipleUpload();
    }
</script>

<input type="hidden" name="Cmd" value="Save" />
<input type="hidden" name="putopts" value="true" /> <!-- Overwrite files -->
<input type="hidden" name="Confirmation-URL" value="<%= Page.Request.Url.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped) %>" />
<input type="hidden" name="PostURL" value="" />
<input type="hidden" name="VTI-GROUP" value="0" />
<input type="hidden" name="destination" id="destination" value="/Documents"> <!-- Files destination path, must already exist -->

<asp:Panel runat="server" Width="100%">
    <script>
        try {
            if (new ActiveXObject("STSUpld.UploadCtl"))
                document.write("<OBJECT id=\"idUploadCtl\" name=\"idUploadCtl\" CLASSID=\"CLSID:07B06095-5687-4d13-9E32-12B4259C9813\" WIDTH=\"100%\" HEIGHT=\"350px\"></OBJECT>");
        }
        catch (error) {
        }
    </script>
    <asp:Button runat="server" accesskey="O" id="OKButton" CssClass="ms-ButtonHeightWidth" Text="Загрузить файлы" UseSubmitBehavior="False" OnClientClick="DocumentUpload(); return false;"/>
    <asp:Button runat="server" accesskey="C" id="CancelButton" CssClass="ms-ButtonHeightWidth" Text="Отмена" UseSubmitBehavior="False" style="display: none;"/>
</asp:Panel>
Что мы имеем:
  1. Скрипт запуска загрузки файлов
  2. Набор параметров, организованных как скрытые поля с атрибутом name
  3. Панель с ActiveX и объектом, отображающими основной интерфейс
  4. Две кнопки – ok и отмена
Все пункты являются обязательными. Если чего-то будет не хватать, то вы получите неприятное окно с ошибкой:
image
1. Скрипт. Тут всё понятно. Находим сгенерированный позже объект и вызываем его метод. Начинается загрузка файлов.
2. Параметры.
  • putopts – указывает необходимость перезаписи файлов, при совпадении имён. Иначе файл не будет загружен
  • destination – указывает путь к папке или библиотеке документов куда необходимо загружать файлы
  • PostURL – теоретически, сюда нужно указать url страницы, которой нужно пересылать файлы, чтобы страница сама определила дальнейшую их судьбу; но на практике это не заработало (компонент сам загружает файлы, по пути указанному в destination)
Параметры можно изменять на лету (JavaScript’ом) перед непосредственным вызовом метода загрузки.
3. ActiveX. Единственный момент тут – данный ActiveX компонент (“STSUpld.UploadCtl”) не должен быть отключен в браузере.
4. Кнопки. Данные кнопки должны существовать. Вы можете их не использовать, скрыть и т.п., но они должны быть. Они должны быть с type=”button” (не “submit”) и у них должны быть проставлены свойства AccessKey.
Ещё несколько особенностей (скажем спасибо Wictor Wilén):
  • Все кнопки на странице должны иметь атрибут AccessKey
  • Должна быть кнопка с AccessKey=”O” (для OK) и AccessKey=”С” (для Cancel)
  • Значение для destination изначально не должно быть пустым, при необходимости его можно изменить позже

четверг, 3 мая 2012 г.

Программное создание страниц веб-частей

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

Решать её необходимо с помощью ProcessBatchData:

/// <summary>
/// Create new webpart page
/// </summary>
/// <param name="list">List to keep page</param>
/// <param name="pageTitle">Page title</param>
/// <param name="layoutTemplate">Layout template id</param>
/// <returns></returns>
private static string CreateWebPartPage(SPList list, string pageTitle, int layoutTemplate)
{
    const string newItemTemplate = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                                    "<Method ID=\"0,NewWebPage\">" +
                                    "<SetList Scope=\"Request\">{0}</SetList>" +
                                    "<SetVar Name=\"Cmd\">NewWebPage</SetVar>" +
                                    "<SetVar Name=\"ID\">New</SetVar>" +
                                    "<SetVar Name=\"Type\">WebPartPage</SetVar>" +
                                    "<SetVar Name=\"WebPartPageTemplate\">{2}</SetVar>" +
                                    "<SetVar Name=\"Overwrite\">true</SetVar>" +
                                    "<SetVar Name=\"Title\">{1}</SetVar>" +
                                    "</Method>";
    var newItemXml = string.Format(newItemTemplate, list.ID, pageTitle, layoutTemplate);

    return list.ParentWeb.ProcessBatchData(newItemXml);
}

 

Применение:

var web = SPContext.Current.Web;
var pagesLibrary = web.GetList("Pages");
CreateWebPartPage(pagesLibrary, "MyPage", 2);

Номера шаблонов для LayoutTemplate:

  1. Целая страница, по вертикали
  2. Верхний колонтитул, нижний колонтитул, 3 столбца
  3. Верхний колонтитул, левый столбец, текстовая область
  4. Верхний колонтитул, правый столбец, текстовая область
  5. Верхний колонтитул, нижний колонтитул, 2 столбца, 4 строки
  6. Верхний колонтитул, нижний колонтитул, 4 столбца, верхняя строка
  7. Левый столбец, верхний колонтитул, нижний колонтитул, верхняя строка, 3 столбца
  8. Правый столбец, верхний колонтитул, нижний колонтитул, верхняя строка, 3 столбца

или тут.