У меня есть веб-страница вне CRM, которая позволяет пользователям выполнять поиск в CRM. Мне нужно реализовать фильтрацию результатов поиска с помощью быстрого поиска, как в обычном пользовательском интерфейсе CRM.
Я получаю FetchXML для выбранной сущности / представления, затем получаю FetchXML для представления быстрого поиска выбранной сущности, извлекаю узел фильтра, где isquickfindfields = 1, заменяю {0} тем, что они ввели в поле поиска, вставляю измененный узел в FetchXML выбранного представления и выполните его.
Проблема, с которой я сталкиваюсь, заключается в том, что некоторые из фильтров быстрого поиска относятся к полю идентификатора связанной сущности, но соответствие должно совпадать с атрибутом первичного имени этой сущности.
Например, вот быстрый поиск сущности аккаунта:
<fetch version="1.0" output-format="xml-platform" mapping="logical">
<entity name="account">
<attribute name="name" />
<attribute name="primarycontactid" />
<attribute name="address1_city" />
<attribute name="telephone1" />
<attribute name="emailaddress1" />
<order attribute="name" descending="false" />
<filter type="and">
<condition attribute="statecode" operator="eq" value="0" />
</filter>
<filter type="or" isquickfindfields="1">
<condition attribute="primarycontactid" operator="like" value="{0}" />
<condition attribute="telephone1" operator="like" value="{0}" />
<condition attribute="emailaddress1" operator="like" value="{0}" />
<condition attribute="accountnumber" operator="like" value="{0}" />
<condition attribute="name" operator="like" value="{0}" />
</filter>
<attribute name="accountid" />
</entity>
And when I plug in the search text and execute the view, I get this error from RetrieveMultiple:
An exception System.FormatException was thrown while trying to convert input value '%acme%' to attribute 'account.primarycontactid'. Expected type of attribute value: System.Guid. Exception raised: Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
Если я использую обычный интерфейс CRM, выполняю поиск по учетным записям и набираю имя контакта в поле быстрого поиска, поиск работает должным образом (перечисляются учетные записи, в которых имя основного контакта - это то, что я ввел). Из-за этого я предположил, что, когда CRM запрашивает базу данных, она «разумно» сопоставляет строки, не относящиеся к Guid, по отношению к основному атрибуту имени ссылки на сущность.
Вот блок кода (pastebin всего метода), который добавляет фильтр быстрого поиска:
if (string.IsNullOrWhiteSpace(searchString) == false)
{
var quickSearch = CRMCache.SavedQueries.FirstOrDefault(q => q.ReturnedTypeCode == view.ReturnedTypeCode && q.QueryType == SavedQueryQueryType.QuickFindSearch);
if (quickSearch != null)
{
var quickSearchXml = XElement.Parse(quickSearch.FetchXml);
var quickSearchFilter = quickSearchXml.XPathSelectElement("//filter[@isquickfindfields=1]");
foreach (var condition in quickSearchFilter.Elements("condition"))
{
condition.SetAttributeValue("value", string.Format(condition.Attribute("value").Value, "%" + searchString + "%"));
}
viewEntityNode.Add(quickSearchFilter);
}
}
Хотя мне любопытно, как с этим справляется обычный пользовательский интерфейс CRM, мой вопрос заключается в том, как мне динамически применять фильтрацию быстрого поиска к запросам / представлениям, которые будут правильно фильтровать по атрибуту основного имени связанной сущности?
[Изменить для пояснения]
Быстрый поиск (или Быстрый поиск) - это один из типов представления в CRM. Он определяет, какие атрибуты ищутся, когда пользователь вводит текст в поле быстрого поиска или при фильтрации поиска. Все объекты имеют представление быстрого поиска, а объект может иметь только одно.
Требование соответствия имени связанной сущности исходит из представления быстрого поиска. Не все из них включают фильтр для ссылки на сущность, но когда он есть, мне нужно сопоставить имя, а не guid. Поскольку обычный пользовательский интерфейс CRM правильно применяет строку поиска к имени связанной сущности, даже несмотря на то, что FetchXML представления быстрого поиска имеет фильтр по идентификатору, я думал, что CRM обработает этот случай внутренне. Очевидно, что это не так (ошибка, которую я получил, показывает это). Поэтому мне нужно обнаружить этот случай и сделать что-то другое, и я хочу делать это динамически.
Говоря динамически, я имею в виду, что в моем коде нет набора предварительно определенных строк FetchXML; он не закодирован для конкретных сущностей, представлений или требований поиска; и его не нужно изменять каждый раз, когда добавляется или изменяется новый объект или представление. Может быть, «динамический» не совсем удачный термин в этом контексте, но я не знаю, как его еще назвать. Независимость от сущности / представления?
Мне не нужен такой код:
SearchResults ExecuteView(string entityLogicalName, string searchString)
{
switch(entityLogicalName)
{
case "account":
return searchAccounts(searchString);
... all other enties ...
default:
throw new Exception("Unknown entity type: " + entityLogicalName);
}
}
SearchResults searchAccounts(searchString)
{
var fetchXml = string.Format(@"
<fetch>
<entity name=""account"">
<link-entity name=""contact"" from=""contactid"" to=""primarycontactid"">
<attribute name=""name"" alias=""name"" />
<filter type=""and"">
<condition attribute=""name"" operator=""like"" value=""%{0}%"" />
</filter>
</link-entity>
</entity>
</fetch>", searchString);
return executeSearch(fetchXml);
}
поскольку изменения в CRM (добавление / удаление объектов, добавление / удаление / обновление представлений) потребуют обновления кода для соответствия.