Разработка
20
Июн
0

Асинхронное обновление записей в CRM

Сегодня рассмотрим как можно асинхронно обновлять записи CRM (в простонародье эта технология называется AJAX). Под асинхронностью понимается, например, вот что… Допустим Вы нажали на форме какую-либо кнопочку которая производит в бэкграунде какие-либо расчеты с последующем обновлением полей формы (либо чере веб-сервис, либо непосредственно на форме). После того как значение поля изменилось обычно необходимо перезагрузить карточку (либо это делается программно – в коде, либо ручкам – по кнопке Сохранить или обновить по F5). По этой причине и была придумана технология AJAX – чтобы производить какие-либо обновления без перезагрузки страницы.

Для примера реализуем такую задачу: через ISV.Config поместим на форму Контакта кнопку, по нажатию на которую будет появляться диалоговое окно поиска лукапа Бизнес-партнера. После выбора Бизнес-партнера из него на текущую карточку Контакта будут перенесены данные двух телефонных номеров. И не просто перенесены визуально, но еще и обновлены в базе данных. В результате чего не нужно будет сохранять (а следовательно и перезагружать) карточку, чтобы внести эти изменения в БД!

Приступим…

  • Для начала добавим на форму Контакта новую кнопку. Экспортируйте ISV.Config и добавьте для объекта Контакт код новой кнопки:
    <Button Icon="/_imgs/ico_18_debug.gif" JavaScript="
    	// Проверяем что у Контакта есть id'ишник
    	if(crmForm.crmForm == 1) {
    		alert('Необходимо сохранить Контакт!');
    	} else {
    		// Открываем диалоговое окно поиска лукап для выбора Бизнес-партнера и результат выбора записываем в переменную str
    		var obejctType = 1;
    		var str = window.showModalDialog('/' + ORG_UNIQUE_NAME +'/_controls/lookup/lookupsingle.aspx?class=null&amp;objecttypes=' + obejctType + '&amp;browse=0&amp;DefaultType=0','','dialogHeight: 450px; dialogWidth: 600px; edge: Raised; center: Yes; resizable: Yes; status: Yes;');
    
    		// Если в диалоге лукапа выбрана запись...
    		if(str!=null) {
    			if(str.items.length > 0) {
    				var accountID = str.items[0].id; // Помещаем в переменную GUID выбранной в диалоге лукапе записи
    				var contactID = crmForm.ObjectId;
    				
    				// ОФормируем URL aspx-страницы, в которую передаем GUID Контакта и Бизнес-партнера
    				var forwardPath = '/isv/ajax/ajax_page.aspx?contactID=' + contactID + '&amp;accountID=' + accountID;
    
    				// Отправляем асинхронный запрос
    				var objXMLHTTP = new ActiveXObject('Microsoft.XMLHTTP');
    				objXMLHTTP.Open('POST',forwardPath,false);
    				objXMLHTTP.Send('');
    
    				// Ответ (номера телефоно разделенные символом '|') помещаем в переменную
    				var response = objXMLHTTP.ResponseText;
    
    				// Если ответ не пустой, то...
    				if (response != null &amp;&amp; response.length != 0) {
    					// Разбиваем строку на подстроки по разделителю |
    					var item = response.split('|');
    
    					// Записываем телефонные номера в соответствующие поля на форме и снимаем с них отметку об изменении
    					document.getElementById('telephone1').value = item[0];
    					document.getElementById('telephone2').value = item[1];
    				}
    			}
    		}
    	}       
    ">
    	<Titles>
    		<Title LCID="1049" Text="Скопировать телефоны" />
    	</Titles>
    	<ToolTips>
    		<ToolTip LCID="1049" Text="Скопировать телефоны" />
    	</ToolTips>
    </Button>
    

    Что тут происходи:

    • По кнопке происходит вызов диалогового окна поиска лукапа для Бизнес-партнера
    • После выбора Бизнес-партнера, его GUID записывается в переменную
    • Далее из GUID’ов Бизнес-партнера и Контакта (открытого в данный момент) формируется URL кастомной ASPX-странички (которую мы создадим позже)
    • После в эту ASPX-страничку посылается запрос и возвращенный ответ, в виде строки с двумя телефонными номерами (Бизнес-партнера, GUID которого мы передали), разделенных символом «|», записывается в переменную.
    • Затем эта переменная разбивается по символу «|» в массив.
    • Элементы массива записываются в поля телефонных номеров формы Контакта. Заметьте что они попадают в поля с помощью getElementById, минуя crmForm (т.е. напрямую), чем мы обходим логику CRM об изменении поля. Поэтому при закрытии формы (без сохранения) форма не будет ругаться 🙂

    P.S. также обратите внимание, что вызов метода objXMLHTTP.Open происходит синхронно (третий параметр – false). Соответственно, чтобы вызвать его асинхронно необходимо заменить false на true 🙂

  • Импортируйте ISV.Config обратно;


  • Далее нужно создать ASPX-страничку, которая будет непосредственно взаимодействовать с CRM сервисом:
    • Создайте asp.net веб-сайт и назовите его MyAjaxApp;
    • Переименуйте страницу default.aspx в ajax_page.aspx. Удалите из нее весь код, кроме строчки:
      <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="ajax_page.aspx.cs" Inherits="_Default" %>
    • Подключите к нему две стандартные сборки из SDK;
    • В ajax_page.aspx.cs добавьте такой код:
      using System;
      using System.Configuration;
      using System.Data;
      using System.Web;
      using System.Web.Security;
      using System.Web.UI;
      using System.Web.UI.HtmlControls;
      using System.Web.UI.WebControls;
      using System.Web.UI.WebControls.WebParts;
      using Microsoft.Crm.Sdk;
      using Microsoft.Crm.SdkTypeProxy;
      using Microsoft.Crm.Sdk.Query;
      
      public partial class _Default : System.Web.UI.Page
      {
          protected void Page_Load(object sender, EventArgs e)
          {
              // Настраиваем CRM Service
              CrmAuthenticationToken myToken = new CrmAuthenticationToken();
              myToken.OrganizationName = "superfirma";
              myToken.AuthenticationType = 0;
              CrmService crmService = new CrmService();
              crmService.Url = "http://win-n22hj23d1b1/MSCrmServices/2007/CrmService.asmx";
              crmService.CrmAuthenticationTokenValue = myToken;
              crmService.UseDefaultCredentials = true;
              crmService.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
      
              // Получаем из строки URL GUID'ы Контакта и Бизнес-партнера
              string accountID = Request.QueryString["accountID"];
              string contactID = Request.QueryString["contactID"];
      
              // Запрашиваем телефонные номера записи Бизнес-партнера
              ColumnSet cols = new ColumnSet();
              cols.AddColumn("telephone1");
              cols.AddColumn("telephone2");
      
              account objAccount = (account)crmService.Retrieve(EntityName.account.ToString(), new Guid(accountID), cols);
      
              // Обновляем запись контакта (новыми телефонными номерами)
              contact objContact = new contact();
              objContact.contactid = new Key();
              objContact.contactid.Value = new Guid(contactID);
              objContact.telephone1 = objAccount.telephone1;
              objContact.telephone2 = objAccount.telephone2;
      
              crmService.Update(objContact);
      
              string telephone1 = (objAccount.telephone1 != null) ? objContact.telephone1.ToString() : "";
              string telephone2 = (objAccount.telephone2 != null) ? objContact.telephone2.ToString() : "";
      
              // Возвращаем (на форму) новые номера телефонов
              Response.Write(telephone1 + "|" + telephone2);
          }
      }
      

      Ну, тут в принципе все просто:

      • Подключаемся к CRM сервису (не забудьте изменить параметры подключения на Ваши 🙂 );
      • Из строки URL выцепляем GUID’ы Контакта и Бизнес-партнера;
      • Из Бизнес-партнера запрашиваем два телефонных номера и обновляем ими аналогичные поля в Контакте (GUID которого был передан);
      • Возвращаем в виде ответа (для размещения на форме) телефонные номера разделенные символом «|».
    • Откройте web.config и поместите туда такой код:
      <?xml version="1.0"?>
      <configuration>
        <appSettings/>
        <connectionStrings/>
        <system.web>
          <httpModules>
            <add name="MapOrg" type="Microsoft.Crm.MapOrgEngine, Microsoft.Crm, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
            <add name="CrmAuthentication" type="Microsoft.Crm.Authentication.AuthenticationEngine, Microsoft.Crm, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
          </httpModules>
          <identity impersonate="true"/>
          <compilation debug="true">
            <assemblies>
              <add assembly="Microsoft.Crm.Sdk, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
              <add assembly="Microsoft.Crm.SdkTypeProxy, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            </assemblies>
          </compilation>
        </system.web>
      </configuration>
      
    • Создайте в папке ISV подпапку ajax. В VS перейдите Duaild — Publish Web Site и в открывшемся диалоговом окне укажите путь к созданной папке ajax (тем самым в нее будут помещены исполнительные файлы asp.net приложения);




  • На этом все… открываем какую-либо карточку Контакта — щелкаем по кнопке — выбираем любую запись Бизнес-партнера — Ок — и смотрим как обновится поля на текущей карточке 🙂 Причем при попытке закрыть ее без сохранения система не будет ругаться на измененные поля, а при повторном Вы увидите все внесенные изменения 🙂


Комментарии (0)

*

code