Passing multiple GUID to QueryExpression

A few time we need to pass multiple parameters to QueryExpression to fetch required entities. I have seen code with multiple calls instead of passing multiple parameters, and of course avoiding multiple calls is efficient.

In code reviews, I also have seen hard coded Guids or people looping through collections to obtain Guids. In some situations, these can be the “only” or best options but often it can be done in a cleaner way using LINQ.

This code example fetches Guids from an entity collection (which are connections) into Guid[] and then use Guid[] as a parameter in query expression.

EntityCollection result = null;       
 
//Getting all GUIDs into a Guid array
        Guid[] guids = connections.Entities.Select(con =>
        con.GetAttributeValue<EntityReference>("record2id").Id).ToArray();

        //Passing guid array in query expression
        QueryExpression query = new QueryExpression("contact");
        query.ColumnSet = new ColumnSet("name");
        query.Criteria.AddCondition(new ConditionExpression("contactid", ConditionOperator.In, guids));
        EntityCollection contacts = organizationService.RetrieveMultiple(query);

I hope it is helpful.

Enjoy your D365 day.

Can’t connect to D365 if system clock is wrong

Probably title of this post summaries it well, but there is some detail worth explanation. I was developing an Azure Function app which was basically integrating data between D365 CE and another system. The major functionality of this application was complete and tested. Two weeks back when I came back from leave I found application (which I was developing), can’t connect to CE now. I was using Microsoft.Xrm.Tooling assembly with the following code but now it started returning null:

public static IOrganizationService GetOrganizationService(ref TraceWriter log)
{
IOrganizationService _orgService = null;
string connectionstring = ConfigurationManager.AppSettings["connectionstring"].ToString();
CrmServiceClient conn = new Microsoft.Xrm.Tooling.Connector.CrmServiceClient(connectionstring);
_orgService = (IOrganizationService)conn.OrganizationWebProxyClient != null ? (IOrganizationService)conn.OrganizationWebProxyClient : (IOrganizationService)conn.OrganizationServiceProxy;
return _orgService;
}

CrmServiceClient has two very useful properties LastCRMError and LastCRMException which were showing this error message:

Unable to Login to Dynamics CRMOrganizationWebProxyClient is nullOrganizationServiceProxy is nullOrganizationServiceProxy is null

Tried looking for solutions and found the following suggestions:

  1. In connection string try Orgnaization unique name instead of friendly name
  2. May be assembly version is not compatible or code/ connection string should be written differently
  3. Use ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; before connection

but none of these worked in my case. I contacted Microsoft support and they confirmed there was no such update or roll out that might have caused this but the good thing is they were still willing to help 🙂

I tried different types of applications, environments and versions but no luck.

In last while testing the following code the error was a little more meaningful:


IServiceManagement orgServiceManagement = ServiceConfigurationFactory.CreateManagement(new Uri("https://myCrmInstance.crm5.dynamics.com/XRMServices/2011/Organization.svc"));

AuthenticationCredentials authCredentials = new AuthenticationCredentials();
authCredentials.ClientCredentials.UserName.UserName = “user@email.com”;
authCredentials.ClientCredentials.UserName.Password = “*********”;
AuthenticationCredentials tokenCredentials = orgServiceManagement.Authenticate(authCredentials);

OrganizationServiceProxy organizationProxy = new OrganizationServiceProxy(orgServiceManagement, tokenCredentials.SecurityTokenResponse);
Entity contact = new Entity(“contact”);
contact.Attributes[“firstname”] = “Yawer”;
contact.Attributes[“lastname”] = “Iqbal”;
var contactId = organizationProxy.Create(contact);

“The security timestamp is invalid because its creation time (‘2019-04-01T12:30:45.790Z’) is in the future. Current time is ‘2019-04-01T12:24:29.185Z’ and allowed clock skew is ’00:05:00′.”

Getting hint about time I found time on my machine is 6 minutes behind. What caused this time change I still don’t know but since it was the difference of just 6 minutes I couldn’t notice this change. Corrected time and everything started working as it was. I thought to do a little experiment and moved clock 6 minutes ahead of current time but this time error was different:

An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.

and inner exception:

An error occurred when verifying security for the message.

Hope this sharing will save someone’s time.

Please feel free to share this post, leave comments or suggestions if there are any. If you like to remain informed about future posts please follow me.

Enjoy this beautiful day of your 365 life 🙂

#D365 #D365CE #MSDynamics

QueryExpression error, “The formatter threw an exception while trying to deserialize the message”

Today I wrote a QueryExpression which was throwing exception “The formatter threw an exception while trying to deserialize the message”.

The complete error message was:

“The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://schemas.microsoft.com/xrm/2011/Contracts/Services:query. The InnerException message was ‘Error in line 1 position 2016. Element ‘http://schemas.microsoft.com/2003/10/Serialization/Arrays:anyType&#8217; contains data from a type that maps to the name ‘http://schemas.microsoft.com/xrm/2011/Contracts:EntityReference&#8217;. The deserializer has no knowledge of any type that maps to this name. Consider changing the implementation of the ResolveName method on your DataContractResolver to return a non-null value for name ‘EntityReference’ and namespace ‘http://schemas.microsoft.com/xrm/2011/Contracts&#8217;.’. Please see InnerException for more details.”

I was using ‘EntityReference’ in a condition, and error message gives hint that somehow there is an issue with ‘EntityReference’ format, and it is not being deserialized correctly. To use ‘EntityReference’ in condition we need to pass its ‘GUID’, and not complete ‘EntityReference’ object.

In the following QueryExpression, the condition will produce a similar exception which can be avoided by passing GUID instead of passing ‘EntityReference’ object as parameter.

QueryExpression query = new QueryExpression();
query.EntityName = “new_document”;
query.ColumnSet = new ColumnSet(“new_name”);
query.Criteria.AddCondition(“new_authorid”, ConditionOperator.Equal,currentDoc.GetAttributeValue<EntityReference>(“new_authorid”));
EntityCollection results =org.RetrieveMultiple(query);

Parent child lookup fields in Dynamic CRM

Showing parent-child records in drop-down lists is a common requirement of business applications.

Some examples:

  1. Manager > Employees
  2. Country > State or Province > City
  3. Account category > Account sub-category > Account number

In Dynamics CRM same behaviour can be implemented by using multiple lookup fields with “Related Records Filtering” which is an out of box CRM feature. For this demo consider an entity “Car Finance Application”, which needs some related details like car brand, model and variant.

a

 

 

Steps:

  • Create the following entities and their relationship as described below:
    • Brand
    • Model, it has N:1 relationship with Brand
    • Variant, it has N:1 relationship with Model
  • Add brand, model and variant lookup fields in consumer entity which in this case is CarFinanceApplication:
  • Add brand, model and variant fields in the form
  • Double click on Model lookup field, and do the “Related Records Filtering”  configurations as shown below:  
  • Double click on Variant lookup field, and do the “Related Records Filtering”  configurations as below:

 

  • Save changes + build customizations + test working of lookup field

Form and lookup fields have been configured and selecting brand will show relevant models. As user selects a model, variant look up will list relevant records but there is a catch. If user changes brand or model after selecting variant, values in three lookup fields will not be in sync. Saving record in such scenarios will basically save  incorrect data  and you will agree many times even user will not realise this. An easy approach to fix this issue can be to reset model and variant look up fields when brand field changes and reset variant lookup field when model field changes.

  • From same form window add the following JS as a code library:
function ClearLookUp() {
for (var counter = 0; counter < arguments.length; counter++) {
if (typeof(arguments[counter]) === "string") {
var field = Xrm.Page.data.entity.attributes.get(arguments[counter]);
if (field != null && field.getValue() != null)
field.setValue(null);
}
}
}
  • Double click on “Brand” lookup field and add “ClearLookUp” javascript function on its “onChange” event. Pass execution context and name of lookup field(s) as comma-separated arguments which will need to reset.

 

  • Double click on “Model” lookup field and call “ClearLookUp” function on its “onChange” event. Pass execution context and name of lookup field(s) as a comma-separated argument.
  • That’s it, test your work and go enjoy a coffee if you like 🙂

Considerations:

  • Any number of lookup fields can be configured with this approach
  • Javascript function is a sort of generic, it can be configured with any lookup field without modification. Also just by calling once it can reset any number of lookup fields, the only requirement will be to pass the name of lookup fields as comma-separated arguments.

Credit:

Before this post, I found a similar implementation by Rashan which I have improved.