Skip to main content

Dynamics CRM API: QueryExpression In Use

During the recent SharePoint 2007 and Dynamics CRM 3.0 integration project I have come across the issue using QueryExpression class of Dynamics CRM API.

Consider the following scenario:
1. We need to search for the contact in CRM using API and following criteria: contact first name and last name are equal to the values provided by search functionality or email is equal to the value provided by search functionality - email = email_value OR (first name = first_name_value AND last name = last_name_value)
2. If contact exists then we just use the identifier to do something with that contact if not exists - create the contact

Initially I wrote the following code to retrieve the desired contact:

string sEmail = ...; // initialize email value
string sFirstName = ...; // initialize first name
string sLastName = ...; // initialize last name

try
{
QueryExpression queryContact = new QueryExpression();
queryContact.EntityName = "contact";
queryContact.ColumnSet = new AllColumns();
queryContact.Criteria = new FilterExpression();
queryContact.Criteria.FilterOperator = LogicalOperator.Or;

ConditionExpression condition1 = new ConditionExpression();
condition1.AttributeName = "emailaddress1";
condition1.Operator = ConditionOperator.Equal;
condition1.Values = new object[] { sEmail };

queryContact.Criteria.Conditions = new ConditionExpression[] { condition1 };

FilterExpression filter1 = new FilterExpression();
filter1.FilterOperator = LogicalOperator.And;

ConditionExpression condition2 = new ConditionExpression();
condition2.AttributeName = "firstname";
condition2.Operator = ConditionOperator.Equal;
condition2.Values = new object[] { sFirstName };

ConditionExpression condition3 = new ConditionExpression();
condition3.AttributeName = "lastname";
condition3.Operator = ConditionOperator.Equal;
condition3.Values = new object[] { sLastName };

filter1.Conditions = new ConditionExpression[] { condition2, condition3 };

queryContact.Criteria.Filters = new FilterExpression[] { filter1 };

BusinessEntityCollection retrievedContacts = service.RetrieveMultiple(queryContact);

if (retrievedContacts.BusinessEntities.Length > 0)
{
gResult = ((contact)retrievedContacts.BusinessEntities[0]).contactid.Value;
}
}
catch (System.Web.Services.Protocols.SoapException soapex)
{
... // error handling
}
catch (Exception ex)
{
... // error handling
}

In my case first name and last name were provided, but email address was empty string. When I ran the code this code - BusinessEntityCollection retrievedContacts = service.RetrieveMultiple(queryContact); - raised an exception: Server was unable to process request. I looked into that very informative exception details and it said "Invalid argument"... After some trial and error process I realized that it was empty condition value that caused an exception.

I changed my code to look as follows:


string sEmail = ...; // initialize email value
string sFirstName = ...; // initialize first name
string sLastName = ...; // initialize last name
string sEmptyValue = "Empty";
try
{
QueryExpression queryContact = new QueryExpression();
queryContact.EntityName = "contact";
queryContact.ColumnSet = new AllColumns();
queryContact.Criteria = new FilterExpression();
queryContact.Criteria.FilterOperator = LogicalOperator.Or;

ConditionExpression condition1 = new ConditionExpression();
condition1.AttributeName = "emailaddress1";
condition1.Operator = ConditionOperator.Equal;
condition1.Values = new object[] { string.IsNullOrEmpty(sEmail) ? sEmptyValue : sEmail };

queryContact.Criteria.Conditions = new ConditionExpression[] { condition1 };

FilterExpression filter1 = new FilterExpression();
filter1.FilterOperator = LogicalOperator.And;

ConditionExpression condition2 = new ConditionExpression();
condition2.AttributeName = "firstname";
condition2.Operator = ConditionOperator.Equal;
condition2.Values = new object[] { string.IsNullOrEmpty(sFirstName) ? sEmptyValue : sFirstName };

ConditionExpression condition3 = new ConditionExpression();
condition3.AttributeName = "lastname";
condition3.Operator = ConditionOperator.Equal;
condition3.Values = new object[] { string.IsNullOrEmpty(sLastName) ? sEmptyValue : sLastName };

filter1.Conditions = new ConditionExpression[] { condition2, condition3 };

queryContact.Criteria.Filters = new FilterExpression[] { filter1 };

BusinessEntityCollection retrievedContacts = service.RetrieveMultiple(queryContact);

if (retrievedContacts.BusinessEntities.Length > 0)
{
gResult = ((contact)retrievedContacts.BusinessEntities[0]).contactid.Value;
}
}
catch (System.Web.Services.Protocols.SoapException soapex)
{
... // error handling
}
catch (Exception ex)
{
... // error handling
}

After the change all works well.


Comments