On a recent project, we were using the OrganizationService, CrmConnection and the Late Bound methodology to build several WCF Services to interact with Microsoft Dynamics CRM 2011.
We experienced some really bizarre behavior which at first, seemed a little hard to understand. We had the following ConnectionString defined for the CrmConnection (I’m obfuscating the client specific values):
<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <clear/> <add name="Main" connectionString="Url=https://***.crminstance/OrgName; Username=***; password=***; /> </connectionStrings> </configuration>
For the first day, I was the only one running the application so nothing seemed out of place. The next day, we had two more developers running the application and all the methods worked as well. We had several more developers start the day after that and two of them had problems. The key point is that everyone was making calls to the services deployed to the Test Environment which used the same connectionString. A few of us were out to lunch and one of the developers, being new to Crm development, assumed that the problem was that he wasn’t a Crm User. This was totally reasonable b/c after each call failed, he attempted to look in Crm to see if he could figure out what went wrong and received and error message indicating he wasn’t a user. After each of the newest devs were added to Crm, their calls started working.
When I got back and heard about the problems, another developer and I started to take a look at things. The other developer noted that each of the records created were created by the person running the code. That seemed really strange. At the same time, I noticed that the password we used for the account was outdated.
Now this was strange- how could this code be running at all? After all the password being used was clearly wrong. The code worked, the Unit Tests passed so we had bigger fish to fry that day although it was something we definitely wanted to circle back around to as soon as we had a few minutes.
All afternoon it bugged me – how could this be working at all? And why weren’t the records being created with the correct owner? I started looking around and decided to change a few things. Originally, the code instantiating the CrmConnection was defined using one of the overloaded constructors:
CrmConnection PrimaryConnection = new CrmConnection("Main");
CrmConnection PrimaryConnection = CrmConnection.Parse("Url=https://***.dynamics.com; Username=***; password=***;");
Not surprisingly, this didn’t change anything (proving only that the overloaded constructor and the Parse method both worked as advertised). I decided to start from scratch and changed the connectionString as follows:
<connectionStrings> <clear/> <add name="Main" connectionString="Url=https://***.dynamics.com; Username=***; password=***; Domain="DomainName"/> </connectionStrings>
Then it all became clear. And of course, this corrected the problem. Can you see what it was? Well, here’s what happened (keep in mind that the initial connectionString had a bad password). When the attempt is made to instantiate the connectionString, it’s parsed and the credentials are used. Since the connectionString had an invalid password, things didn’t work. Once the password was fixed, it was missing the Domain name. So in both cases, the cached user credentials for the user running the code was used. Once the domain was added and the password was corrected, the parse operation ran successfully and a valid user and password was found on the domain, so the specified user credentials were passed in.
One other thing worth throwing in. Securing your connectionStrings is an important security consideration and there are built in mechanism for securing your connectionString information. Frequently however companies will chose to use an existing Cryptography library to Encrypt and Decrypt their data. Assume then, that you were using a custom library that had a Static Decrypt method. You can use it in conjunction with the Parse method (b/c the overloaded constructors use the Name of the connectionString or a ConnectionStringSetting object):
String DecryptedConnectionString = CryptoLibrary.Decrypt(ConfigurationManager.ConnectionStrings["CrmMain"].ConnectionString; var connection = CrmConnection.Parse(DecryptedConnectionString);
And once you have a valid CrmConnection, creating an OrganizationService or
CrmOrganizationServiceContext is as easy as passing it into the respective object's constructor:
String DecryptedConnectionString = CryptoLibrary.Decrypt(ConfigurationManager.ConnectionStrings["CrmMain"].ConnectionString; var ConnectionInstance = CrmConnection.Parse(DecryptedConnectionString); // Declare and Instantiate OrganizationService var ServiceInstance = new OrganizationService(ConnectionInstance); // OR???
// Declare and Instantiate CrmOrganizationServiceContext
String DecryptedConnectionString = CryptoLibrary.Decrypt(ConfigurationManager.ConnectionStrings["CrmMain"].ConnectionString; var ConnectionInstance = CrmConnection.Parse(DecryptedConnectionString); var ContextInstance = new CrmOrganizationServiceContext(ConnectionInstance);
If you have any questions or comments, just let us know: firstname.lastname@example.org
KeyWords: Microsoft.Xrm.Sdk.Entity, Crm 2011, Dynamics CRM 2011, Microsoft.Xrm.Client.CrmConnection, RelatedEntities, CrmConnection, Microsoft.Xrm.Client, CrmOrganizationServiceContext , OrganizationService, CrmConnection.Parse, CrmConnection.Parse, Dynamics4, Dynamics4.com