Dynamics CRM закладки

Многие уже используют такие закладки для Dynamics CRM от Benjamin John, для тех же кто только хочет их использовать сделал небольшое дополнение — собрал Dynamics CRM Bookmarklets в один файл, который можно легко импортировать к себе в браузер.

Например в Google Chrome: Settings  — Bookmarks — Import bookmarks and settings — choose  From Bookmarks HTML File. 

В результате получите папку Imported, с вложенными подпапками и ссылками на удобные Bookmarklets. MS CRM 2015 Bookmarklets

Скачать архив можно здесь — Dynamics CRM Bookmarklets V2

Ошибки с Plugin registration tool и MS CRM 2015 Online

Ошибка 1. Время от времени при попытке подключиться к MS CRM 2015 Online с помощью  Plugin registration tool стал получать ошибку:

Source : mscorlib
Method : HandleReturnMessage
Date : 03.11.2015
Time : 19:08:55
Error : Отметка времени безопасности недействительна, так как ее время создания («2015-11-03T19:00:04.000Z») относится к будущему. Текущее время: «2015-11-03T17:08:55.364Z», допустимая разница в показаниях часов: «00:05:00».

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

Панель управления — Часы, язык и регион — Дата и время — Время по Интернету.

sync_time_internet

 

Ошибка 2. При попытке подключиться получил ошибку «Error : Authentication Failure DefaultURL». Детали лога:

Error : Незащищенное или неправильно защищенное сообщение об ошибке было получено от другой стороны. Код ошибки и описание см. внутреннее исключение.

…..

Error : Authentication Failure DefaultURL

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

Хотя со входом в веб-часть MS CRM 2015 Online проблем не возникало.

Если ошибок возникает много, то лог файл разрастается в размере и последние ошибки будут в самом конце файла. Удалить лог файл Login_ErrorLog.log от Plugin registration tool можно по адресу: C:\Users\admin\AppData\Roaming\Microsoft\Microsoft Dynamics© CRM Plug-in Registration Tool

Нюансы недавних Rollup -ов

Пара последних роллапов (Rollup 10 / 11) с одной стороны решают часть накопившихся проблем, а с другой, как порой это бывает, приносят с собой дополнительные «неожиданности»:)

Вот, например, некоторые из них, с которыми мы столкнулись недавно:

1. После установки роллапа (ставился сразу 11) попытка экспортировать Default Solution заканчивается ничем. После нажатия кнопки Next браузер просто не загружает файл солюшена. (При этом прочие Solutions могут быть экспортированы нормально).

Заглянув в Fiddler, наблюдаем не слишком информативную ошибку  “Invalid Argument”.

Включив tracing, находим в куче следующее сообщение:

Crm Exception: Message: A non valid page number was received: 0, ErrorCode: -2147220989

На данный момент возможное лечение это проблемы видеться только следующее: необходимо найти ключ TurnOffFetchThrottling в реестре и установить его значение в 0; затем перезапустить IIS. Скорее всего, если вы столкнулись с подобной ошибкой, то у вас текущее значение этого ключа равно 1.

«Внешние» симптомы, приводящие к подобной ошибке в трейсе, могут быть различные. Например, в этой статье http://www.interactivewebs.com/blog/index.php/server-tips/crm-2011-rollup-10-invalid-argument-error/ рекомендуется указанное решение в случае проблем загрузки изображений в IFD среде.

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

2. «Microsoft Dynamics CRM Asynchronous Processing Service (maintenance)» Windows  Service остановился и не мог стартовать.  Ошибка в логах Windows показала, что проблема связана запуском одной из scheduled job, которая имела период запуска несколько месяцев. Система, похоже, не воспринимала период в месяцах. Замена периода в месяцах на соответствующий период в днях решила проблему, и сервис запустился. Детальней копать причину такого поведения времени пока не было.

3. Похоже на то, что поведение плагинов зарегистрированных на Stage 50 немного изменилось. Как известно, Stage 50 предназначен только для обратной совместимости с плагинами CRM 4.0, где те могут быть зарегистрированы. Если до установки роллапа, 100 процентов вызовов на этом этапе шли уже за пределами транзакции, то после установки роллапа около 7% вызовов стали проходить внутри основной транзакции. Для некоторых специфических интеграционных подходов, использующих «старые 4.0» плагины на данном этапе, это может быть критично так как может вызвать блокировки в базе данных.  Но тут по большому счёту не «придерёшься»:). Майкрософт заявляет, что на этом этапе часть вызовов все-таки может проходить внутри транзакции. Просто раньше, до указанных роллапов, такого не наблюдалось, и этим можно было пользоваться. В общем, отсутствие в MS CRM 2011 этапа, который бы гарантированно выполнялся после основной операции и за пределами транзакции, можно рассматривать ряде случаев как недостаток функционала (мы рассматрваем тут синхронный вариант выполнения плагина).

4. Стили в Currency полях немного исказились. Вот как выглядит поле после роллапа:

Говорят эта проблема будет решена в 12 роллапе. Если такое форматирование нервирует довольно сильно, то на этой ветке форума можно посмотреть временное unsupported решение, связанное с модификацией базовых стилей:

http://social.microsoft.com/Forums/en-US/crm/thread/f3d8cb21-448b-4dc9-9cdc-3d5c91969adc

Кроме указанных выше случаев, можно обратить внимание на эту пару статей:

http://social.technet.microsoft.com/wiki/contents/articles/13437.update-rollup-10-for-microsoft-dynamics-crm-2011.aspx

http://social.technet.microsoft.com/wiki/contents/articles/14101.update-rollup-11-for-microsoft-dynamics-crm-2011-en-us.aspx

Они содержат интересные заметки о прочих возможных потенциальных проблемах, которые могут появиться после установки 10 и 11 пакета обновления.

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

Надеемся, что последующие пакеты обновлений для MS CRM будут более стабильны:)

Удачи!

Pavel Khorozhansky email: khorozhansky@gmail.com

Business units или Подразделения в CRM 2011

Для чего нужны подразделения

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

Кроме того, идеология Подразделения реализует один из трех механизмов управления доступом к данным: на уровне Подразделений, в дополнении к Ролям безопасности (security roles) и к Политике безопасности полей (fields security).

Суть управления доступом с использованием понятия Подразделения заключается в следующем. Если принадлежность сущности – «пользователь» (а не «организация»), то можно определить уровень доступа к экземплярам сущности: никому, только владельцу, пользователям своего Подразделения, пользователям своего и дочерних (подчиненных) Подразделений, всем.

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

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

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

Однако если Роли безопасности всегда создаются на уровне root, то тогда использование Подразделения в качестве аккумулятора нужного набора Ролей теряется. Поскольку для всех дочерних (по отношению к root) Подразделений будет создан одинаковый, что и у root, набор копий Ролей безопасности (подробнее см. Роли безопасности).

Особенности

Головное подразделение

Может быть только одно. Создается автоматически при развертывании CRM.

Головное Подразделение не имеет родительского подразделения.

Головное Подразделение – root – нельзя удалить или сделать неактивным.

Остальные подразделения

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

Циклические связи между Подразделениями не поддерживаются.

Переименовывать можно любое активное Подразделение.

Подразделение можно отключить. Достаточно сделать его неактивным. Неактивное Подразделение становится read only.

Однако неактивному Подразделению можно назначить другое головное Подразделение.

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

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

Пользователи неактивного Подразделения не могут подключаться к CRM.

Ресурсы и команды неактивного Подразделения не удаляются, но становятся недоступными для использования (выбора).

Чтобы удалить Подразделение, нужно сначала сделать его неактивным.

При переносе пользователя из одного Подразделения в другое (изменить Подразделение у пользователя) удаляются все его роли. Нужно назначать заново вручную.

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

Нельзя назначить Роли безопасности подразделению. Однако это можно сделать с одноименной Рабочей группой.

Роли безопасности привязываются к Подразделению. Т.е. любое Подразделение имеет свой набор Ролей безопасности (см. Роли безопасности). Соответственно пользователям Подразделения могут быть назначены только Роли безопасности, которые привязаны к текущему Подразделению либо которые унаследованы из родительского (и выше) Подразделения.

Для определения того, какие Роли безопасности есть у Подразделения, следует использовать Расширенный поиск по Ролям безопасности с критерием «Родительская роль не содержит данных».

Важно

В документации к CRM 2011 сказано, что переименовывать и удалять Подразделения нельзя. На самом деле – можно (удалять нельзя только root). См. выше.

Добавляем фото пользователя в CRM 2011

Ниже приводится один из простых и элегантных способов размещения фотографии пользователя в карточке пользователя Microsoft Dynamics CRM 2011.

Известно решение на базе Silverlight, в котором изображение хранится в примечании, а затем подгружается в форму. Однако добавить подобную функциональность можно проще, используя JScript и web ресурсы.

Краткое описание решения:

Фотография пользователя хранится в виде веб-ресурса.

Ссылка на веб-ресурс с фото помещается в поле photourl записи о пользователе, а значит, фото становится доступно во всех сущностях (и отчетах в том числе), в которых имеется привязка к пользователю.

Ссылка на фото (поле photourl) обновляется автоматически при открытии карточки пользователя и при обнаружении соответствующего веб-ресурса с фото.

Описанное решение пригодно, в первую очередь, для пользователей CRM, поскольку записи о пользователях хранятся от момента их регистрации до исключения из организации и не меняют своих Id. Регистрация пользователя в CRM – событие довольно редкое, поэтому можно себе позволить уделить немного времени на загрузку фото в виде веб-ресурса (с последующей публикацией ресурса).

Реализация.

  1. Выбираем фото неизвестного пользователя. Это фото будет загружено в виде веб-ресурса с именем UnknownUser, и затем будет отображаться в карточках тех пользователей, которые не имеют своих фотографий. Масштабируем и кадрируем фото, чтобы получить разрешение 100 х 133 пикселей (вы можете использовать другое разрешение на свое усмотрение).
  2. Выбираем фото пользователя. Масштабируем и кадрируем фото пользователя в разрешение 100 х 133. Для всех фото используем тип PNG.
  3. Создаем тестовое решение. В нем создаем ресурс для хранения изображения в формате PNG. Добавляем фото неизвестного пользователя:

  1. Открываем запись пользователя, фото которого мы подготовили, и копируем ссылку на запись. Секрет использования фото в виде веб-ресурса состоит в правильном именовании ресурса. Имя ресурса с фото образуется путем прибавления к префиксу уникального идентификатора записи пользователя, в котором убраны все знаки ‘-‘. Вот что должно получиться:

  1. Публикуем оба созданных веб-ресурса. А затем добавляем сущность Пользователь (systemuser).

  1. Открываем форму сущности Пользователь и вставляем в нее веб-ресурс – неизвестное фото. Параметры настройки веб-ресурса показаны ниже:

  

  1. Редактируем раскладку полей на форме на свой вкус. Например, так:


Не забываем добавить на форму поле photourl и скрыть это поле.

  1. Создаем и загружаем в CRMследующий JScript (логика его работы откомментирована):
if (typeof (Demo) == "undefined")
{ Demo = { }; }                                                     // пространство имен
 
Demo.User = {                                             // имя контейнера
//*************************************************************************
// Обработчики событий для формы Пользователь
//*************************************************************************
        // Инициализация
        //---------------------------------------------------------------------
        init : function ( )
        {
               this.setPhoto();
        },
        //----------------------------------------------------------------------     
        // Задание фотографии пользователя
        //----------------------------------------------------------------------     
        setPhoto : function ( )
        {     
               try
               {
                       // ищем элемент, где записана ссылка на ресурс с фото
                       var element = document.getElementById("WebResource_UserPhoto");                                                  
                       // вешаем на element обработчик успешной  загрузки WebResource                                                   
                       element.onload = function ()                                                                                                                                         
                       {
                              Xrm.Page.getControl("WebResource_UserPhoto").setVisible(true);                            // показываем фото
                              Xrm.Page.getAttribute("photourl").setValue(url);                                            // сохраняем в поле photourl правильный url
                       }
                       // вешаем на element обработчик ошибки загрузки WebResource                                                
                       element.onerror = function ()                                                                                                                                        
                       {
                              Demo.User.setImageUrl(element,"new_Photo_UnknownUser");                  // грузим фото UnknownUser
                              Xrm.Page.getControl("WebResource_UserPhoto").setVisible(false);           // на всякий случай
                       }
                       var url = Xrm.Page.getAttribute("photourl").getValue();                                         // считываем URL фото пользователя
                       // если url на фото еще не установлен или в поле photourl хранится ссылка на UnknownUser
                       If ( url == null || url.search(/UnknownUser/i) != -1 )                                                                                          
                              // конструируем url с фото пользователя и пытаемся загрузить
                              // важно использовать правильную последовательность знаков в регулярном выражении
                              // {-} работать не будет, поскольку является специальной конструкцией регулярного выражения
                              // В функции setImageUrl произойдет вызов element.setAttribute(url) - поэтому нужно else ниже
                              this.setImageUrl(element,"new_Photo_" + Xrm.Page.data.entity.getId().replace(/[{}-]/g, "").toUpperCase());      
                       else
                              element.setAttribute("src",url);                                          // пытаемся загрузить фото по url в поле photourl
               }
               catch (e) { }
        },
        //----------------------------------------------------------------------     
        // Конструирование url и его загрузка
        //----------------------------------------------------------------------     
        setImageUrl : function ( element, imageName )
        {
               var serverUrl = Xrm.Page.context.getServerUrl();
               if ( serverUrl.match(/\/$/) )                                                              // если есть адрес сервера заканчивается на /
                       serverUrl = serverUrl.substring(0, serverUrl.length - 1);          // убираем конечный слэш
               var url = serverUrl + "/WebResources/" + imageName;                 // конструируем url
               Xrm.Page.getControl("WebResource_UserPhoto").setSrc(url);      // устанавливаем атрибут ресурса "src" на url с фото
        }     
};
  1. Публикуем и добавляем скрипт на форму; устанавливаем обработчик события открытия формы на функцию init().

  1. Публикуем решение и проверяем его работу:

 

Успехов! Sergiy.Yezhov@gmail.com