Implement all types of queries when filtering results using PreOperation RetrieveMultiple

Category: Design, Performance, Security, Supportability

Impact potential: Medium

Symptoms

RetrieveMultiple calls from different applications display different results.

  • For example: same views in legacy applications show different results in new applications.

Guidance

Note

The Retrieve and RetrieveMultiple messages are typically the most commonly used messages. Plug-ins for these messages can significantly impact system performance. Generally, you should avoid using plug-ins for these messages if the requirements can be achieved some other way. More information: Limit the registration of plug-ins for Retrieve and RetrieveMultiple messages

Plug-ins registered on the RetrieveMultiple message are typically intended to filter the results returned by queries for an entity. There are two strategies to do this using a plug-in registered on either the PostOperation or PreOperation stages.

PostOperation filtering

In the PostOperation stage, evaluate the records returned in the OutputParameters BusinessEntityCollection Entities property and remove entities that shouldn't be returned.

This approach potentially changes the expected number of records returned in each page of results and can result in inconsistent experiences when the data is displayed in an application.

PreOperation filtering

In the PreOperation stage, evaluate the InputParameters Query property and adjust the query to filter what is returned before it's executed.

When using this approach you must implement the appropriate filtering for the different possible types of queries, most importantly: FetchExpression and QueryExpression. If you implement just one of these, different applications that use the other type of query don't apply your changes.

Although the QueryExpressionToFetchXml and FetchXmlToQueryExpression messages provide the capability to convert one query type to another, because of the performance impact of including more calls within RetrieveMultiple, we recommend that you don't use these messages in this context. Rather, implement your filtering using the equivalent logic in both.

There's a third type of query that can also be used with RetrieveMultiple: QueryByAttribute. This type of query doesn't provide for complex filtering and it isn't possible to include more complex filtering logic within a plug-in. Fortunately, this type of query isn't frequently used. Depending on the sensitivity of the filtering you add, you might choose to reject queries of this type by throwing an InvalidPluginExecutionException.

Example

See Sample: Modify query in PreOperation stage for an example of the strategy we recommend.

Problematic patterns

When someone writes a plug-in to change the records returned in a specific application that uses just one type of query used by that application, either FetchExpression or QueryExpression, the results might not be consistent in other applications or if the application changes the type of query used. Write plug-ins that provide the same result regardless of the application.

Additional information

When using the Web API, GET requests on a collection are converted to QueryExpression unless the query uses FetchXml as described in Retrieve and execute predefined queries. In that case the queries use FetchExpression.

Unified Interface replaced the legacy web client for model-driven apps. Unified Interface uses the FetchXml defined in the SavedQuery.FetchXml or UserQuery.FetchXml properties. For better performance, Unified Interface doesn't convert the FetchXml data to a QueryExpression before executing these queries as the legacy web client did. Therefore, queries that were modified in plug-in code for the legacy web client that used QueryExpression don't apply the same changes now that the query to support views is being passed using FetchExpression unless the plug-in code is written to apply same logic to FetchExpression queries.

See also

Sample: Modify query in PreOperation stage
Query data using the SDK for .NET
Query data using FetchXml
Build queries with QueryExpression
Limit the registration of plug-ins for Retrieve and RetrieveMultiple messages
Unified Interface Community