我在CRM之外有一个网页,允许用户执行CRM查找。我需要像普通的CRM UI一样使用快速搜索来实现对查询结果的过滤。
我获取了所选实体/视图的FetchXML,然后获取了所选实体的快速搜索视图的FetchXML,提取了isquickfindfields = 1的过滤器节点,将{0}替换为其在搜索框中键入的内容,将修改后的节点插入所选视图的FetchXML,然后执行它。
我遇到的问题是某些快速搜索过滤器针对相关实体的id字段,但是匹配项必须针对该实体的“主要名称”属性。
例如,以下是帐户实体的快速搜索:
<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>
当我插入搜索文本并执行视图时,我从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在查询数据库时,它将“智能地”匹配实体引用的主名称属性中的非古德字符串。
这是添加快速搜索过滤器的代码块(整个方法的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 UI如何处理此问题时,我的问题是如何动态对将正确根据相关实体的主名称属性进行过滤的查找/视图动态应用快速搜索过滤?
[为澄清而编辑]
快速搜索(或快速查找)是CRM中的一种视图类型。它定义了当用户在快速搜索框中输入文本或过滤查找时将搜索哪些属性。所有实体都有一个快速搜索视图,一个实体只能有一个。
匹配相关实体名称的要求来自快速搜索视图。并非所有人都在实体引用上包含过滤器,但是当这样做时,我需要根据名称而不是guid进行匹配。由于普通的CRM UI正确地将搜索字符串应用于相关实体的名称,即使快速搜索视图的FetchXML具有针对ID的过滤器,我也认为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中的更改(添加/删除实体,添加/删除/更新视图)将需要更新代码以匹配。
最佳答案
我不知道CRM如何使用字符串搜索GUID来摆脱可推测性,但是我怀疑它会执行一些预处理或某些后端内容,而这些东西可能对您来说不可用。 (我想如果您真的想知道您可以尝试反编译CRM .dll,但这可能需要一段时间)。
因此,作为替代方案,我建议您进一步处理FetchXml的处理阶段,如果借助元数据服务执行此操作,则应该无需任何硬编码就可以摆脱困境。
因此,以获取帐户为例,我认为您需要编辑xml,以便id属性附加name
,例如primarycontactidname
。那是FilteredView中数据库列的名称,我相信它可以从FetchXml获得。 (如果这样不起作用,请在名称中添加link-entity
过滤器,并删除现有条件)。
因此,您知道何时添加name
,我建议:
检索快速查找视图的搜索条件。
对于每种情况,请使用元数据服务搜索CRM
如果字段类型为EntityReference
,则使用适当的条件更新快速查找视图搜索。