понедельник, 30 ноября 2015 г.

SharePoint. Ошибка WebDAV при открытии библиотеки в проводнике. Нет доступа.

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


Текст ошибки:
Нет доступа к \\server\DavWWWRoot\site\library. Возможно, у вас нет прав на использование этого сетевого ресурса. Обратитесь к администратору этого сервера для получения соответствующих прав доступа.
Присоединенное к системе устройство не работает.


На английском языке:
\\server\DavWWWRoot\site\library is not accessible. You might not have permission to use this network resource. Contact that administrator of this server to find out if you have access permissions.
A device attached to the system is not functioning.

Несмотря на то, что в тексте ошибки речь идёт о правах доступа, к реальности это не имеет никакого отношения. Когда библиотека документов открывается в проводнике windows, то используется протокол WebDAV. Ошибка происходит из-за ограничений на получение количества данных по этому протоколу. Настройки хранятся в реестре Windows. Чтобы исправить описанную выше ошибку, необходимо сделать следующие шаги:

  • Откройте редактор реестра - regedit.
  • Перейдите к ветке реестра: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WebClient\Parameters\
  • Найдите ключ реестра FileAttributesLimitInBytesfor
  • Если его нет, то создайте ключ FileAttributesLimitInBytesfor с типом DWORD.
  • Дальше необходимо изменить его значение. Для удобства измените систему исчисления. Изначально скорее всего будет отмечена шестнадцатеричная:

    Поменяйте на десятичную и задайте значение 50000000, это максимальное значение:
После этого необходимо перезапустить службу "Веб-клиент":
net stop webclientnet start webclient
После выполнения этих шагов библиотека открылась через проводник.
Проблема в том, что эти настройки делаются на клиенте. Вероятно потребуется их распространить через GPO.

пятница, 30 октября 2015 г.

SharePoint. Фильтрация пользователей в PeoplePicker


Изначально в выдачу поля типа "Пользователь" попадают все пользователи домена Active Directory и из доменов с которыми установлены доверительные отношения:



В моём случае мне необходимо было отфильтровать некоторых пользователей. Мне не нужны были пользователи без email адреса, к примеру служебные учётные записи. Т.е. не показывать пользователей с пустым или отсутствующим атрибутом mail из AD. Так же я хотел, чтобы PeoplePicker показывал мне пользователей как в адресной книге из Exchange. Адресная книга не отображает пользователей AD, у кого поле msExchHideFromAddressLists установлено в TRUE.

Поведение PeoplePicker'а можно настроить  через утилиту STSADM.EXE, которая находиться в файловой системе по адресу: C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\BIN, так же можно использовать PowerShell.

Для того, чтобы выполнить описанные выше условия, необходимо выполнить следующую команду в STSADM.EXE:

stsadm -o setproperty -pn peoplepicker-searchadcustomfilter -pv "(&(mail=*) (!msExchHideFromAddressLists=TRUE))" -url http://server

Можно делать более сложные условия, например делать как в примере выше, но при этом всё равно отображать особенных пользователей. Их особенность в том, что у них атрибут extensionAttribute5 установлен в "Show":

stsadm -o setproperty -pn peoplepicker-searchadcustomfilter -pv "(|(&(mail=*)(!msExchHideFromAddressLists=TRUE))(extensionAttribute5=Show))" -url http://server

Чтобы просмотреть какой сейчас фильтр установлен - можно выполнить команду:

stsadm -o getproperty -url http://portal -pn peoplepicker-searchadcustomfilter

Для сброса фильтрации:

stsadm -o setproperty -pn peoplepicker-searchadcustomfilter -pv " "

Узнать подробнее про запросы к Active Directory можно по ссылке:

https://technet.microsoft.com/en-us/library/aa996205(EXCHG.65).aspx


SharePoint. Группировка по году создания.

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


Назовите его "Год". И задайте значение поля "Формула" вот так: "=ГОД(Дата)" или "=ГОД(Создано)", если вы не создавали отдельного столбца для хранения даты.
Функция "Год()" может быть вам уже знакома из Microsoft Excel.
Важно отметить, что если у вас другой язык в SharePoint, то и формула должна быть написана на соответствующей языке.

После создания столбца "Год" - он будет заполнен значением года. Теперь необходимо создать новое представление и группировать элементы по полю "Год":





Результат должен быть как на картинке:



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

среда, 30 сентября 2015 г.

SharePoint. Ошибка при просмотре представлений списков.


Внезапно перестали отображаться представления списков. Вместо представления был текст:
"Ну удалось завершить эту операцию" и номер идентификатора взаимосвязи:
По номеру ошибки удалось найти текст исключения:
Error while executing web part: Microsoft.SharePoint.SPException: Не удалось завершить эту операцию.  Повторите попытку. ---> System.Runtime.InteropServices.COMException: Не удалось завершить эту операцию.  Повторите попытку.<nativehr>0x80004005</nativehr><nativestack></nativestack>
    at Microsoft.SharePoint.Library.SPRequestInternalClass.GetTimeZoneInfo(Int32 lcid, UInt16& pwTimeZoneID, Object& pvarBias, Object& pvarStandardDate, Object& pvarDaylightDate, String& pbstrDescription, String& pbstrKeyName)
    at Microsoft.SharePoint.Library.SPRequest.GetTimeZoneInfo(Int32 lcid, UInt16& pwTimeZoneID, Object& pvarBias, Object& pvarStandardDate, Object& pvarDaylightDate, String& pbstrDescription, String& pbstrKeyName)     --- End of inner exception stack trace ---
    at Microsoft.SharePoint....

...SPGlobal.HandleComException(COMException comEx)
    at Microsoft.SharePoint.Library.SPRequest.GetTimeZoneInfo(Int32 lcid, UInt16& pwTimeZoneID, Object& pvarBias, Object& pvarStandardDate, Object& pvarDaylightDate, String& pbstrDescription, String& pbstrKeyName)
    at Microsoft.SharePoint.SPTimeZone.EnsureTZData()
    at Microsoft.SharePoint.SPTimeZone.get_Information()
    at Microsoft.SharePoint.WebPartPages.XsltListViewWebPart.ModifyXsltArgumentList(ArgumentClassWrapper argList)
    at Microsoft.SharePoint.WebPartPages.DataFormWebPart.PrepareAndPerformTransform(Boolean bDeferExecuteTransform)

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

Это решило проблему.




четверг, 27 августа 2015 г.

SharePoint 2013. Меню для узла.


Обычно узел имеет текущую навигацию слева, как показано на рисунке:


Но порой необходимо как-то выделить часто используемые ссылки.
Можно использовать возможности html, но не все пользователи смогут это сделать.
В SharePoint 2013 есть прекрасный механизм для решения этой задачи. Он называется "Рекомендуемые ссылки". Это список. Чтобы его создать перейдите в "Весь контент сайта"-> "Добавить приложение" и выберите "Рекомендуемые ссылки":
После создания списка надо разместить его на главной странице. Поскольку список пуст - надо его заполнить данными. Помимо названия и ссылки можно добавить картинку, чтобы выглядело красивее. В моём случае все ссылки вели на списки SharePoint, неплохо бы было иметь для этого понятные картинки, как в меню создания списков (приложений). Используя инструменты разработчика (вызов через F12) можно посмотреть адреса картинок:


Ниже, чтобы Вам сэкономить время, есть таблица с адресами иконок для некоторых списков:


 Задачи /_layouts/15/images/lttask.png?rev=23
 Документы /_layouts/15/images/ltdl.png?rev=23
 Календарь /_layouts/15/images/ltevent.png?rev=23
 Обсуждения /_layouts/15/images/ltdisc.png?rev=23
 Контакты /_layouts/15/images/ltcontct.png?rev=23

После заполнения список в представлении "Все рекомендуемые ссылки" выглядел так:


А в представлении "Мозаика" выглядит так:
Самое главное - это возможность конфигурировать меню для конечного пользователя, без навыков HTML & CSS. 

среда, 29 июля 2015 г.

SharePoint. jQuery page scroll



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

Все будет реализовано на JavaScript, jQuery и немного CSS c HTML.
Для быстрого просмотра результата создадим отдельную страницу и добавим на нее полный текст рыбы. Рыбу можно взять здесь. Теперь нам нужно добавить JavaScript код, для этого разместим на странице веб-часть "редактор сценариев" и вставим код ниже:



<script src="/SiteAssets/Script/jQuery/jquery-1.11.0.min.js"></script>
<script>
function  HandleScroll() {
// Навешиваем обработку на событие движения колеса мыши
var offsetY = 300;
$('#s4-workspace').scroll(function () {
        if ($(this).scrollTop() > offsetY) {
            //Стрелка появись
            $('.scrollUpBtn').fadeIn();
        } else {
            //Стрелка исчезни
            $('.scrollUpBtn').fadeOut();
        }
    });

// Навешиваем обработку на событие клика по стрелке
$('.scrollUpBtn').click(function (){
        $('#s4-workspace').animate({scrollTop:0},'slow');
        return false;
    });
};
_spBodyOnLoadFunctionNames.push("HandleScroll");
</script>

После этого добавим на страницу веб-часть "редактор контента" и добавим в нее стили:

<style>
.scrollUpBtn{
    width:100px; 
    height:130px;
    padding:10px; 
    text-align:center; 
    background: whiteSmoke;
    font-weight: bold;
    color: #444;
    text-decoration: none;
    position:fixed;
    top:75px;
    right:40px;
    display:none;
    background: url('https://cdn2.iconfinder.com/data/icons/freecns-cumulus/16/519703-211_CircledBorderArrowUp-64.png') no-repeat 0px 20px;
}
.scrollUpBtn:hover{
    text-decoration:none;
}
</style>

Теперь остается добавить в веб-часть "редактор контента" строчку с html разметкой
<a href="#" class="scrollUpBtn"></a>

Как это выглядит в итоге:

вторник, 30 июня 2015 г.

SharePoint. Как послать email используя JavaScript


У меня возникла необходимость послать email сообщение c формы элемента, сделав это асинхронно из JavaScript. В JSOM я не нашел такой возможности.

Способ № 1
Первое что пришло в голову - сделать на C# веб-часть, которая будет брать данные из url и отсылать почту, код выглядит достаточно коротким:

using (var oSite = new SPSite(SPContext.Current.Web.Url))
using (var oWeb = oSite.OpenWeb(SPContext.Current.Web.ServerRelativeUrl))
{
    string to, subject, body;
    to = Page.Request.QueryString["to"];
    subject = Page.Request.QueryString["subject"];
    body = Page.Request.QueryString["body"];
                
    var headers = new StringDictionary
        {
            {"to", to},
            {"subject", subject},
            {"content-type", "text/html"}
        };
        SPUtility.SendEmail(oWeb, headers, body);
}


Теперь нам необходимо вызвать серверной код GET запросом, код на JavaScript & jQuery будет выглядеть так:

// Отсылаем уведомление
function  SendMail(to, subject, body) {
    $.ajax({
        url: '/SitePages/SendMail.aspx',
        type: 'GET',
        data: { to: to, subject: subject, body: body },
        contentType: 'application/json; charset=utf-8',
        success: function  (response) {
            console.log("success send email to secretary");
        },
        error: function  () {
            console.log("error");
        }
    });
}


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

Способ № 2
Есть другой пусть. Как известно, мы можем слать письма используя рабочий процесс, так же мы знаем о возможности создавать элементы списка используя JSOM. Т.е. можем создать JavaScript'ом элемент списка, на создании которого запуститься рабочий процесс и отошлет письмо. Чтобы у рабочего процесса была информация куда, с какой темой и что слать - создадим соответствующие поля в списке. Наш элемент списка  должен  иметь 3 столбца:
  • Кому
  • Тема
  • Тело
Итак, у нас будет функция которая будет написана на JavaScript и использовать JSOM для создания элемента в списке:

// Создаем элемент списка
function CreateEmailListItem(emailListTitle, to, subject, body) {
    var clientContext = new SP.ClientContext.get_current();
    var oList = clientContext.get_web().get_lists().getByTitle(emailListTitle);
    var itemCreateInfo = new SP.ListItemCreationInformation();
    this.oListItem = oList.addItem(itemCreateInfo);

    oListItem.set_item('To', to);
    oListItem.set_item('Subject', subject);
    oListItem.set_item('Body', body);
    oListItem.update();
    clientContext.load(oListItem);

    clientContext.executeQueryAsync(function.createDelegate(this, this.onQuerySucceededEmailListItem), function.createDelegate(this, this.onQueryFailedEmailListItem));
}

function onQuerySucceededEmailListItem() {
    console.log('(Успех. Элемент списка создан.)Item created: ' + oListItem.get_id());
}

function onQueryFailedEmailListItem(sender, args) {
    console.log('Request failed. (Ошибка. Элемент списка не создан.)' + args.get_message() + '\n' + args.get_stackTrace());
}

После создания элемента будет срабатывать рабочий процесс отсылающий письмо. Для этого нам нужно одно действие рабочего процесса:



В редакторе необходимо настроить действие:


Для начала заполним отправителя:


Аналогично необходимо заполнить поля "Тема" и "Тело":


Теперь действие рабочего процесса заполнено:

 Необходимо опубликовать рабочий процесс и обязательно отметить пункт "Автоматически запускать рабочий процесс при создании элемента":
 Теперь попробуем вызвать нашу JavaScript функцию:

CreateEmailListItem('emailList', 'Ulmaskulov_ar@Borets.ru', 'subject', 'body')

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

P. S. Не забудьте разобраться с правами на список, иначе пользователи смогут читать сообщения отправленные не им.
Рекомендую перейти в настройки списка: Параметры -> Дополнительные параметры -> Разрешения на уровне элементов -> Доступ на чтение и отметить "Чтение элементов, созданных пользователем". Выглядит это так:


Способ № 3
После публикации ссылки на пост в фейсбуке, в комментариях, мне подсказали еще один способ. Вероятно, это самый удобный из всех возможных. Спасибо Denis Molodtsov и Иван Горбадей.
Суть способа заключается в отправке запроса к SharePoint REST API.
Код выглядит так:

function SendEmail(from, to, body, subject) {
    var siteurl = _spPageContextInfo.webServerRelativeUrl;
    var urlTemplate = siteurl + "/_api/SP.Utilities.Utility.SendEmail";
    $.ajax({
        contentType: 'application/json',
        url: urlTemplate,
        type: "POST",
        data: JSON.stringify({
            'properties': {
                '__metadata': { 'type': 'SP.Utilities.EmailProperties' },
                'From': from,
                'To': { 'results': [to] },
                'Body': body,
                'Subject': subject
            }
        }
        ),
        headers: {
            "Accept": "application/json;odata=verbose",
            "content-type": "application/json;odata=verbose",
            "X-RequestDigest": $("#__REQUESTDIGEST").val()
        },
        success: function(data) {
            alert("Email sent");
        },
        error: function(err) {
            alert(err.responseText);
        }
    });
};