5
votes

Caching behavior of the last Dynamics SDK is driving me crazy.

First, if you want to use CrmServiceClient to access different environments you have to use the parameter RequireNewInstance=True; in the connection string. If not, every instance of CrmServiceClient will use the same connection, even if you create and dispose instances to different environments.

Now, even if you use the RequireNewInstance=True; in the connection string I found that cache still occurs in some scenarios.

var client1 = new CrmServiceClient("RequireNewInstance=True;
Url=https://myCompany.crm.dynamics.com;
[email protected]; Password=myPassowrd;
AuthType=Office365");

//Now, client 2 points to a url that doesn’t exists:
var client2 = new CrmServiceClient("RequireNewInstance=True; 
Url=https://xxx.crm.dynamics.com; [email protected]; 
Password=myPassowrd; AuthType=Office365");

The client2 keeps using the first connection string, so you cannot determine if the new connection string is correct.

Any ideas how to test Dynamics Crm connections strings correctly in my asp.net application?

3

3 Answers

3
votes

Late reply, but the behavior you're seeing is because when you're specifying an erroneous URL the discovery service is used to ascertain which instance to connect to. To prevent this specify SkipDiscovery=True in your connection string:

var connectionString2 = @"AuthType=Office365;Url=https://FAKE.crm.dynamics.com;Username=USERNAME;Password=PASSWORD;RequireNewInstance=True;SkipDiscovery=True;";

Edit: SkipDiscovery is true by default starting with 9.0.7, kudos to @mwardm

2
votes

I think I found the problem. It seems to only happens on Dynamics 365 online trials, that was the reason we were getting inconsistent results depending on the environment.

Apparently, the url doesn't need to be completely valid to establish a connection to a CRM online trial environment, as long as the credentials are valid and the url structure is kept.

Let's consider the following example:

var client1 = new CrmServiceClient("RequireNewInstance=True; 
Url=https://fake.crm.dynamics.com; 
[email protected]; Password=myPassowrd; 
AuthType=Office365");

In this case I can substitute the "fake" part of the url with whatever I want, but still execute requests correctly using the CrmServiceClient service.

If I try to do this with another environment (e.g. 2015, on premise, not-trial crm online, etc.), the IsReady property of the CrmServiceClient would return false and I would get an error in the LastCrmError property.

Very weird behavior, and difficult to pinpoint. Now that I think I understand the inconsistent behavior I know that finally it will not affect our clients, so I will mark this response as the answer even if I still do not know why we have different behavior between a trial and a normal environment..

1
votes

I agree choosing to reuse the existing connection if you don't include RequireNewInstance=true seems counter-intuitive, but I can't reproduce what you're seeing. If I try the following from LinqPad crmSvcClient2 will print out errors and then throw a null ref on the Execute call (8.2.0.2 version of the SDK). With this version of the SDK you'll want to always check LastCrmError after connecting to see if the connection failed.

var connectionString = @"AuthType=Office365;Url=https://REAL.crm.dynamics.com;Username=USERNAME;Password=PASSWORD;RequireNewInstance=True;";
var connectionString2 = @"AuthType=Office365;Url=https://FAKE.crm.dynamics.com;Username=USERNAME;Password=PASSWORD;RequireNewInstance=True;";   

using (var crmSvcClient = new CrmServiceClient(connectionString))
{
    "crmSvcClient".Dump();
    crmSvcClient.LastCrmError.Dump();
    ((WhoAmIResponse)crmSvcClient.Execute(new WhoAmIRequest())).OrganizationId.Dump();
    crmSvcClient.ConnectedOrgFriendlyName.Dump();


}
using (var crmSvcClient2 = new CrmServiceClient(connectionString2))
{
    "crmSvcClient2".Dump();
    crmSvcClient2.LastCrmError.Dump();
    ((WhoAmIResponse)crmSvcClient2.Execute(new WhoAmIRequest())).OrganizationId.Dump();
    crmSvcClient2.ConnectedOrgFriendlyName.Dump();
}

enter image description here