LINQPad connections to Dynamics 365 online – Part 3 – Using myextensions to encapsulate your connection code

In the first part of this multi-part series of articles about creating connections in LINQPad to Dynamics 365 online, I went through the basic steps needed to create an OrganizationService connection in a LINQPad script.

The second article explained how to manage MFA protected accounts.

In this third article, I will explain how we can improve things by encapsulating all of this logic into a couple of useful methods which allow us to connect to Dynamics 365 by simply typing a single line of code.

Using ‘My Extensions’ to encapsulate this into a single ‘login’ command

Clearly, we don’t want to have to type all of the code from the previous articles into LINQPad every time we want to connect to Dynamics365. Using the MyExtensions class, we can very easily encapsulate all of the above logic into a single method, so that when you want to create a  connection to one of your Dynamics 365 instances, all you need to type is something like this:

IOrganizationService service = MyExtensions.ConnectToCrm(MyExtensions.Environments.DEV);

The MyExtensions class allows us to create reusable methods and other reusable components. To access the file, you can find and double click on the file from the ‘My Queries’ pane, or by using the shortcut Shift+Ctrl+Y:
My Extensions in the My Queries Pane
When you first open the MyExtensions file, you will see something like this:
My extensions before editing

Let’s start by defining an enum, listing the different environment we might want to connect to:

public enum Environments

Now you can add a ‘ConnectToCrm’ method in MyExtensions which takes one of these ‘environments’ as a parameter, and use a switch statement to build your connection string and connect to Dynamics 365:

public static IOrganizationService ConnectToCrm(Environments environment)
	// Your code here - it might look something like this...
	string username = Util.GetPassword("d365_username");
	string password = Util.GetPassword("d365_password");

	string instance = "";

	switch (environment)
		case Environments.DEV:
			instance = "thenameofyourdevinstance";

		case Environments.TST:
			instance = "thenameofyourtestinstance";
        // switch for other environments...

	string connectionString = "RequireNewInstance=True;AuthType=Office365;Url=https://"+ instance + "; Username=" + username + "; Password=" + password;
	ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

	OrganizationServiceProxy orgService = new CrmServiceClient(connectionString).OrganizationServiceProxy;

	Console.WriteLine("Connected to " + orgService.ServiceConfiguration.ServiceEndpoints.First().Value.Address.Uri);
	Entity user = orgService.Retrieve("systemuser", ((WhoAmIResponse)orgService.Execute(new WhoAmIRequest())).UserId, new ColumnSet("fullname", "domainname"));
	Console.WriteLine("Logged in as: " + user["fullname"] + " Domain Name: " + user["domainname"] + "\n");

	return orgService;

NB: You must compile your MyExtensions file by hitting f5 before the code becomes available in your other scripts.

Now all you need to do to connect to the environment of your choice in any LINQPad script is to select one of your preconfigured environments:
Choosing from a lost of environments

Connecting to multiple environments at the same time

One of the advantages in using this method of logging in, compared to a pre-configured LINQPad connector, is that it allows you to connect to more than one environment in a single script, to compare data or maybe to move data from one environment to another.

void Main()
    IOrganizationService svcDev = MyExtensions.ConnectToCrm(MyExtensions.Environments.D365DEV);    
    IOrganizationService svcTest = MyExtensions.ConnectToCrm(MyExtensions.Environments.D365TST);
    CountUsers(svcDev).Dump("# Users in Dev");
    CountUsers(svcTest).Dump("# Users in Test");	

private int CountUsers(IOrganizationService service)
    return ((EntityCollection)service.RetrieveMultiple(new QueryExpression("systemuser"))).Entities.Count;

which will give a result like this:
Comparing the number of users in different environments

Do you really want to log into production?
Another feature which you can add to your MyExtensions code is a warning when a user is about to log into production. This can be very useful in preventing someone from accidentally running a script against a production instance. We can easily do this by using LINQPad’s Util.ReadLine method to prompt the user to confirm if they want to connect to Production:

public static bool WarnIfConnectingToProduction(Environments environment)
	//Warn if user is connecting to a Production environment
	switch (environment)
		case Environments.PRD:
		String carryOn = Util.ReadLine<String>("Connecting to a production environment - Do you want to continue? Y/N").ToUpper();

		if (carryOn != "Y" && carryOn != "N")
			Console.WriteLine("You should have typed Y or N");
			Console.WriteLine("Process aborted");
			return false;
		else if (carryOn == "N")
			Console.WriteLine("Process aborted");
			return false;
        return true;

A prompt will appear at the bottom of the page, asking for confirmation when a Production instance is chosen:
Warning if connecting to Production instance

Adding Impersonation to our MyExtensions code
In this article, I explained how impersonating users can be very useful in diagnosing problems, or testing what happens when code as different users with different security roles. Adding an Impersonate method to your MyExtensions method can make this very straightforward.

Impersonating Another User

Sharing the love

Once you have created your methods in your Myextensions file, you can share this with the rest of the team, using the method outlined in this article. If you all set your  ‘Plugins and Extensions’ folder to the same folder in your Source Control system, you can all connect to Dynamics in exactly the same way without having to share any passwords.

Posted in Dynamics 365, LINQPad | Leave a comment

Leave a Reply