Показаны сообщения с ярлыком SharePoint. Показать все сообщения
Показаны сообщения с ярлыком SharePoint. Показать все сообщения

вторник, 31 мая 2016 г.

SharePoint. Вывод всех полей UPSA используя Powershell

Ниже представлен небольшой скрипт для вывода основных полей из User Profile Service Application. Помимо тривиального перебора свойств Microsoft.Office.Server.UserProfiles.UserProfileManager, стоит отметить наличие столбца, в котором указано привязанное поле в Active Directory и направление синхронизации. Так же есть небольшая особенность вывода значений в файл.

# Почистить вывод
cls
# Получить оснастку
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
# Указываем имя подключения (имя можно посмотреть по адресу:http://CA:port/_layouts/15/mgrdsserver.aspx?ApplicationID={GUID})
$connectionName = "MyConnectionName"
# Адрес коллекции
$siteUrl = "http://server:port"
# Получаем коллекцию
$site = Get-SPSite $mySiteUrl
# Получаем SPServiceContext
$context = Get-SPServiceContext $site
# Получаем все необходимые объекты
$profileConfigManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileConfigManager($context)
$syncConnection = $profileConfigManager.ConnectionManager[$connectionName]
$profileManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)
$propertyList = New-Object System.Collections.Generic.List[System.Object]
# Формируем список
foreach ($p in $profileManager.properties) 
{    
    $propertyObject = New-Object PSObject
    # Системное имя
    $propertyObject | Add-Member Name $p.Name
    # Отображаемое имя
    $propertyObject | Add-Member DisplayName $p.DisplayName
    # Переводы на интересующие языки (Ru)
    $propertyObject | Add-Member LocalRU $p.DisplayNameLocalized[1049]
    # Переводы на интересующие языки (En)
    $propertyObject | Add-Member LocalEN $p.DisplayNameLocalized[1033]
    # Тип  
    $propertyObject | Add-Member Type $p.Type
    # Размер поля
    $propertyObject | Add-Member Length $p.Length
    # Синхронизируемое поле в АД
    $pm = $syncConnection.PropertyMapping[$p.Name]
    $propertyObject | Add-Member PropertyNameAD $pm.DataSourcePropertyName
    # Направление синхронизации   
    $propertyObject | Add-Member IsImportFromAD $pm.IsImport 
    # Обязательность
    $propertyObject | Add-Member IsRequired $p.IsRequired
    # Параметр конфиденциальности 
    $propertyObject | Add-Member DefaultPrivacy $p.DefaultPrivacy
    # Возможность переопределения конфиденциальности
    $propertyObject | Add-Member UserOverridePrivacy $p.UserOverridePrivacy
    # Возможность изменения пользователем
    $propertyObject | Add-Member IsUserEditable $p.IsUserEditable
    # Отображение на странице просмотра
    $propertyObject | Add-Member IsVisibleOnViewer $p.IsVisibleOnViewer
    # Отображение на форме изменения
    $propertyObject | Add-Member IsVisibleOnEditor $p.IsVisibleOnEditor
    # Индексация (в смысле доступен для поиска)
    $propertyObject | Add-Member IsSearchable $p.IsSearchable
    # Добавить в список
    $propertyList.Add($propertyObject)   
}
# Выводим список на экран в отдельном окне в сетке
$propertyList | Out-GridView
# Выводим список в текстовый файл с заголовками 
$propertyList | Format-Table -Property * -AutoSize ` | Out-String -Width 4096 ` | Out-File C:\FileName.txt

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



Обратите внимание на кусочек вывода в файл. Необходимо указывать "Out-String" чтобы строки не обрезались.

пятница, 29 апреля 2016 г.

SharePoint. Переводные столбцы списка.

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


Для того, чтобы столбец стал переводным – необходимо задать его имя выражением:
$Resources:fileWithDict,key;

Где:
$Resources – признак выражения
fileWithDict – файл словаря, должен находиться по адресу “C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\Resources” и иметь имя fileWithDict.ru-ru.resx, ru-ru это культура.
key – ключ по которому ищется значение в файле-словаре

Задать переводное имя столбца можно даже при создании через web-интерфейс, вместо имени надо вписать выражение:


На самом деле там не словарь, а xml. Но вы об этом не думайте и воспринимайте как словарь.

Чтобы система показала соответствующий язык – ей надо знать предпочтения пользователя.
Чтобы указать языковые предпочтения перейдите в раздел "Мой язык и регион" как на картинке:

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


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



















Выбираем языковые параметры:

















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

Кстати, именно таким образом заданы встроенные поля. Проверим это созвав настраиваемый список и выведем все поля в представление:


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


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

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

понедельник, 29 февраля 2016 г.

SharePoint.Создать ярлык документа.

SharePoint позволяет создавать ярлыки к документам.
Ярлык выглядит так:



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

В разделе "Дополнительные параметры" выбрать:


После разрешения управлять типами контента списка, в настройках появится блок "Типы контента". Под ним есть ссылка на добавление типа контента к списку. Перейдите по ссылке "Добавить из существующих типов контента":



Из окна с доступными типами выберите "Связь с документом":




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





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

Появится форма создания, заполните ее, нажмите "ОК":


А потом еще раз "ОК":


В библиотеке появится элемент как в самом начале статьи:


При клике произойдет переход по указанной ссылке. В нашей ссылке в url был установлен параметр "Web=1", значит офисный документ сразу откроется в Office Web Apps:


Что именно произошло? Была создана страница .aspx:

Работу по перенаправлению в ней выполняет элемент SharePoint:UrlRedirector.


понедельник, 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)

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

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




среда, 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);
        }
    });
};

понедельник, 1 июня 2015 г.

SharePoint. Error: Cannot complete the copy or merge operation because the database schema versions are different


Ошибка возникла при попытке перенести коллекцию сайтов в другую базу данных контента.
Как это делать можно узнать по ссылке. Если кратко, то необходимо выполнить следующий PowerShell коммандлет:

Move-SPSite <http://ServerName/SiteName> -DestinationDatabase <DestinationContentDb>

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

В моём случае необходимо было обновить схему БД источника.
На картинке видно, что БД контента (WSS_Content), откуда мне необходимо перенести коллекцию сайтов - требует обновления, в отличии от БД контента в которую будет перемещена коллекция (WSS_Content_SSTD):

Что бы точно узнать версии схем - клик по имени базы, на отдельной странице будут написаны подробные сведения о БД:



Для обновления БД контента необходимо выполнить PowerShell скрипт:

Upgrade-SPContentDatabase <DB Name>

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

(Get-SPDatabase <DB_id> ).Provision();

После обновления БД контента Вы увидите следующее:


Теперь ошибка о разности схем исчезнет и можно выполнить перенос коллекции сайтов.

пятница, 29 мая 2015 г.

SharePoint. Идентификатор взаимосвязи. Как читать ошибки.


SharePoint, при возникновении ошибки не показывает текст, а сообщает "Correlation ID" (Идентификатор взаимосвязи). Выглядит это так:


Сам текст ошибки можно найти в файле журнала ошибок:
C:\Program Files\Common Files\Microsoft Shared\web server extensions\14\LOGS

Для удобного просмотра текста ошибки ( и других событий) по Correlation ID есть много инструментов, часть создана еще для прошлых версий SharePoint, актуальными можно считать только 2:
1) SharePoint ULS Viewer

2) SharePoint LogViewer

Обе программы имеют возможность поиска теста ошибки или любого другого события по Correlation ID.

четверг, 30 апреля 2015 г.

SharePoint 2013 Workflow error. Exception details: System.FormatException: Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).


В ходе выполнения рабочего процесса возникла ошибка:
RequestorId: f54a5d97-39ba-7d44-0000-000000000000. Details: An unhandled exception occurred during the execution of the workflow instance. Exception details: System.FormatException: Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). at System.Guid.GuidResult.SetFailure(ParseFailureKind failure, String failureMessageID, Object failureMessageFormatArgument, String failureArgumentName, Exception innerException) at System.Guid.TryParseGuidWithNoStyle(String guidString, GuidResult& result) at System.Guid.TryParseGuid(String g, GuidStyles flags, GuidResult& result) at System.Guid.Parse(String input) at System.Activities.CodeActivity`1.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager) at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)

Вот так выглядит на странице состояния рабочего процесса (wrkstat.aspx):


В своем рабочем процессе я создал свой тип контента на основе задачи рабочего процесса 2013 версии. Пользователь при выполнении задачи заполняет добавленное мною кастомное поле. После завершения задачи я пытаюсь использовать значение заполненного поля. В действии назначения задачи есть возможность сохранять GUID созданной задачи в переменную. Используя эту переменную (TaskId14 на картинке) в подстановке я могу получить значение моего кастомного поля "Примечание":

Ошибка, описанная в начале статьи, возникает в случае если Вы пробуете достать элемент задачи используя не GUID. Т.е. просто перепутали поле и вместо TaskId14, как в моем случае, используете любое другое значение, которое не является GUID.

понедельник, 27 апреля 2015 г.

SharePoint. Ссылка на загрузку документа.

Порой возникает необходимость дать ссылку на загрузку документа в библиотеке SharePoint.
Чтобы ссылка была именно на загрузку копии документа. В случае если это файл, который можно открыть в Office Web Apps, то у меня возникла ситуация когда документ из браузера Internet Explorer выдается на открытие:



После открытия этого документ в клиенте, т.е. в Microsoft Office Word 2013 - мы имеем возможность редактировать именно версию которая находится на сервере:




Нам же необходимо получить именно загруженную копию. Для этого надо передать путь скачиваемого файла как параметр странице download.aspx

http//host/_layouts/download.aspx?SourceUrl=http://host/library/myDoc.docx:

В случае, если в имени скачиваемого документа имеется кириллица, то необходимо предварительно выполнить кодирование URL. Ниже показан пример как это сделать, если Вы формируете ссылку на клиенте с использованием JavaScript:
var downloadPageUrl = "http://host/_layouts/download.aspx?SourceUrl=";
var souceFileUrl = "http://host/library/мойДокумент.docx";
var encSouceFileUrl = encodeURIComponent(souceFileUrl);
var downloadUrl = downloadPageUrl + encSouceFileUrl;
В общем проблема решается. Сама страница download.aspx наследуется от класса Download из сборки Microsoft.SharePoint.ApplicationPages.dll, в которой событие "OnLoad" читает параметр "SourceUrl" из URL и выдает полученный файл в виде потока байт с MIME-типом application/octet-stream: