ユーザーが CRM ルックアップを実行できるようにする、CRM の外部の Web ページがあります。通常の 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 がデータベースにクエリを実行すると、エンティティ参照のプライマリ名属性に対して非 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 UI がこれをどのように処理するのか興味がありますが、私の質問は、関連するエンティティのプライマリ名属性に対して正しくフィルター処理するルックアップ/ビューにクイック検索フィルター処理を動的に適用するにはどうすればよいですか?
[明確化のために編集]
クイック検索(またはクイック検索) は、CRM のビュー タイプの 1 つです。ユーザーがクイック検索ボックスにテキストを入力するとき、またはルックアップをフィルタリングするときに、どの属性が検索されるかを定義します。すべてのエンティティにはクイック検索ビューがあり、エンティティは 1 つのみを持つことができます。
関連するエンティティの名前と一致するという要件は、クイック検索ビューに由来します。それらのすべてにエンティティ参照のフィルターが含まれているわけではありませんが、含まれている場合は、GUID ではなく名前と照合する必要があります。クイック検索ビューの FetchXML には id に対するフィルターがありますが、通常の CRM UI は関連するエンティティの名前に対して検索文字列を正しく適用するため、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 の変更 (エンティティの追加/削除、ビューの追加/削除/更新) に合わせてコードを更新する必要があるためです。