В Microsoft Dynamics CRM 3.0 для расширения базовой бизнес-логики использовались callout (колауты), представляющие собой dll-сборки, которые можно было подключать на определенные сущности и события, предварительно запрограммировав необходимый функционал.
В Microsoft Dynamics CRM 4.0 callout переименовали в plug-in (плагин) и добавили дополнительные возможности. Более подробно сейчас не будем останавливать на перечислении всех возможностей plug-in, а рассмотрим простой пример.
Я приведу пример обновления поля new_companyname в task при выборе определенной записи из поля «В отношении» (regardingobjectid). Например, если выбран контакт и он относится к организации, то получаем имя родительской организации (account)
Примечание: пример плагина есть в SDK, он создает объект сущности Task (Задачу) после создания нового объекта сущности Account (Организация).
Подготовка рабочего окружения
- Установить MS Visual Studio 2008 (можно и 2005)
- Обязательно скачать SDK для MS CRM 4.0
- скачаем шаблон проекта для плагина.
- качаем PluginRegistration tool – этот инструмент поможет нам легко зарегистрировать плагин
Visual Studio установили, теперь кидаем скачанный архив MSCRM Plug-in.zip по пути (у меня так)
C:\Documents and Settings\<Имя пользователя>\Мои документы\Visual Studio 2008\Templates\ProjectTemplates\Visual C#
(теперь, по умолчанию в проект будут подключены необходимые библиотеки, но очень рекомендую для начала изучить SDK)
При создании нового проекта на C# у нас появилась возможность выбрать наш шаблон

MS CRM Plug-in шаблон
- Сразу подпишем нашу сборку: Правой кнопкой в студии на проекте – Properties – Signing – Sign the assembly – Choose a strong name key file – new – указываете имя файла, галочку Protect my key file with a password – снимаете, Сохраняете.
Подключим Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.Sdk.Query;
В плагинах, в отличие от колаутов, используется один основной метод Execute. Мой метод для этого примера выглядит так:
public void Execute(IPluginExecutionContext context)
{
DynamicEntity entity = null;if (context.InputParameters.Properties.Contains(ParameterName.Target) &&
context.InputParameters.Properties[ParameterName.Target] is DynamicEntity)
{entity = (DynamicEntity)context.InputParameters.Properties[ParameterName.Target];
if (context.MessageName != MessageName.Update.ToString()
&& context.MessageName != MessageName.Create.ToString())
{
throw new InvalidPluginExecutionException(«Smth wrong with Update stage may be»);
}}
else
{
return;
}try
{ICrmService crmService = context.CreateCrmService(false);
if(entity.Properties.Contains(«regardingobjectid»))
{
String new_companyname = «»;
ColumnSet cs = new ColumnSet();
Lookup regarding = (Lookup)entity.Properties["regardingobjectid"];
// проверяю что за объект передаю в лукапе: организация/контакт/возможная сделка/интерес// проверяю, что в лукапе выбрана Организация
if (regarding.type == EntityName.account.ToString())
{
cs.Attributes.Add(«name»);
account _account = (account)crmService.Retrieve(EntityName.account.ToString(), regarding.Value, cs);
if (_account == null || _account.name == null)
{
return;
}else
{
new_companyname = _account.name.ToString();
}
}// проверяю, что в лукапе выбран Контакт
if (regarding.type == EntityName.contact.ToString())
{
cs.Attributes.Add(«parentcustomerid»);
contact _contact = (contact)crmService.Retrieve(EntityName.contact.ToString(), regarding.Value, cs);if (_contact == null ||
_contact.parentcustomerid == null ||
(_contact.parentcustomerid.IsNull &&
_contact.parentcustomerid.IsNullSpecified) ||
_contact.parentcustomerid.type != EntityName.account.ToString())
{
return;
}
else
{
new_companyname = _contact.parentcustomerid.name.ToString();
}
}// проверяю, что в лукапе выбрана Возможная сделка
if (regarding.type == EntityName.opportunity.ToString())
{
cs.Attributes.Add(«customerid»);
opportunity _opportunity = (opportunity)crmService.Retrieve(EntityName.opportunity.ToString(),regarding.Value, cs);
if (_opportunity == null ||
_opportunity.customerid == null)
{
return;
}
else
{
new_companyname = _opportunity.customerid.name.ToString();
}
}
// проверяю, что в лукапе выбран Интерес
if (regarding.type == EntityName.lead.ToString())
{
cs.Attributes.Add(«companyname»);
lead _lead = (lead)crmService.Retrieve(EntityName.lead.ToString(), regarding.Value, cs);
if (_lead == null ||
_lead.companyname == null)
{
return;
}
else
{
new_companyname = _lead.companyname;
}
}// обновляем наше поле
![]()
entity.Properties.Add(new StringProperty(«new_companyname», new_companyname));
}
}
Компилируем плагин и переходим к регистрации плагина.
Регистрация плагина с помощью PluginRegistration tool
Для регистрации используем ранее скачанный PluginRegistration tool, указываем параметры для соединения с CRM-сервером и регистрируем нашу сборку:
- Register -> Register New Assembly (Ctrl + A)
- Указываем AKPuginActivity.dll (C:\Documents and Settings\Администратор\Мои документы\Visual Studio 2008\Projects\AKPuginActivity\AKPuginActivity\bin\Debug) и оставляем выбор сохранения в базе данных.
- Выбираем нашу сборку и регистрируем новый Step
- Register -> Register New Step (Ctrl+T)
- Message: Create; Primary Entity: task; Stage of Execution: Pre Stage

Регистрируем новый Step для плагина
Повторяем шаги 4 и 5, только для события Update (Message: Update)
Проверяем работу
Создаем новую задачу и в поле «В отношении» выбираем контакт, у которого есть родительская организация. Сохраняем и в поле new_companyname появится название организации. Проверяем обновление выбрав другую запись.
Примечание:
Поле new_companyname у меня присутствует не только в сущности task, но и letter, phonecall, appointment в каждой из этих стандартных сущностей присутствует поле «В отношении» regardingobjectid поэтому достаточно зарегистрировать еще несколько step для каждой из сущностей и код будет отрабатывать корректно
Отдельное спасибо Андрею Бутенко за отзывчивость
Ознакомьтесь со статьей «Отладка plug-ins для Microsoft Dynamics CRM 4.0» для эффективной отладки ваших плагинов.
