Site Maps and Custom Entities – Oh My!

You can now create your own groups and areas in Dynamics365 giving you further customization over your user’s experience in the application when accessing your custom entities.

I recently got a chance to play with this and was really impressed with it’s simplicity.

Note: This does not replace the security permissions to your entities which must be in place alongside these changes which are User Interface only.

You can see from my screenshot that you can add new areas (in my case “Custom”), new groups (in my case “My Goodies”) and then Subareas (in my case I dropped in a new custom entity but there are other options here too.


Once done, you can publish direct from this editor.

I’ve highlighted the name of the Sitemap that I’m in, right now this is for Customer Service specifically.  However, if you look at the components of my solution you will see I have imported a few different Sitemaps that will trigger based on the settings of my users.


If you’ve never had to modify a SiteMap before in XML (so sorry, that was loads of fun) to do this, you go to “Client Extensions” in your Solution view and when you select “Add to Existing” you presented with either the SiteMap or Application Ribbon as options.


Using Dynamics365 as a Queue for Data Synchronization

Over the years, I’ve migrated a lot of data from on-premise systems into Dynamics365 (whether they be existing CRM system, homegrown solutions or off the shelf packages).  I’ve used a number of third-party tools to accomplish these tasks (Scribe and Kingsway) but have also written my own when the need arose.

On a recent project, faced with yet more synchronization requests and the need for more infrastructure to manage changes, mediate conflicts, prevent ping-ponging data writes, etc, etc.  I started to change my thinking from being able to have everything on-premise (i.e., the ability to queue up new Virtual Images and tons of server space et al) to think of how I solve this problem if all I had was Dynamics365 and the server I am moving data from.

To start with – how could I keep up-to-date with all the changes happening in Dynamics and queue them up for later retrieval by some other system.

My first thought was an async workflow to do the job but this raised up a few other requirements in doing this;

  1. Administrators should be able to associate this workflow to any new entity they want synced with super ease (i.e., create workflow, finish).
  2. The code for the workflow should not need to be modified at all and should dynamically figure out the entity and primary key attribute that I need to later retrieve to be synced.
  3. Code should be small.

So here is what I wrote as a workflow and then deployed to my online tenant.  The solution is really tiny, I created an entity called syn_dataeventqueue, which contains all the synchronization entries.

I did some tests between custom and core entities and was able to detect the proper change events coming in and for the correct entities.  You can see the initial state is “Not Processed” – I created some custom states for when I pull the requests to not pull again if the syncing period went longer than expected but that’s for another post – here is the code.

 protected override void Execute(CodeActivityContext Execution)
 //Get the Tracing Service
 ITracingService tracingService = Execution.GetExtension<ITracingService>();

 //get context
 IWorkflowContext context = Execution.GetExtension<IWorkflowContext>();
 //create iorganization service object
 IOrganizationServiceFactory serviceFactory = Execution.GetExtension<IOrganizationServiceFactory>();
 IOrganizationService service = serviceFactory.CreateOrganizationService(context.InitiatingUserId);

 //Now we need to query the entity for their primary id.
 RetrieveEntityRequest request = new RetrieveEntityRequest();
 request.EntityFilters = EntityFilters.Attributes;
 request.LogicalName = context.PrimaryEntityName;

 RetrieveEntityResponse response = (RetrieveEntityResponse)service.Execute(request);
 AttributeMetadata PrimaryAttribute = response.EntityMetadata.Attributes.Where(a => a.IsPrimaryId == true && a.AttributeType == AttributeTypeCode.Uniqueidentifier && a.ColumnNumber == 1).FirstOrDefault();
 string AttributeName = PrimaryAttribute.SchemaName.ToLower();

 Entity EntityToSync = (Entity)service.Retrieve(context.PrimaryEntityName, context.PrimaryEntityId, new ColumnSet(AttributeName));

 tracingService.Trace("Trace| Record to Synchronize: Entity [{0}], Id [{1}].", context.PrimaryEntityId.ToString(), context.PrimaryEntityName.ToString());

 if (EntityToSync.Contains(AttributeName))
 Entity SyncroEntity = new Entity("syn_dataeventqueue");
 SyncroEntity["syn_name"] = context.PrimaryEntityName;
 SyncroEntity["syn_entityrecordid"] = context.PrimaryEntityId.ToString();
 catch (Exception ex)
 tracingService.Trace("Error| Synchronization Submission Exception: {0}", ex.ToString());

The only piece you are probably wonder about is the search for ColumnNumber to be 1.  In my tests, this is always the primary id field, when I tried searching for simply the IsPrimaryId it brought back results for the primary ids of related entities so that didn’t work.

Here is how things look in the workflow creation itself.


One step!

And what does it look like in Dynamics?


Beautiful – now to finish the rest of it.


Getting Started with Windows IoT

I recently bought a Windows IoT kit from Adafruit and started to play around with it last week.  IoT (Internet of Things) is one of those things that I don’t use during the day job and instead, I’m playing with completely on my own.

I should also note that this is my first foray into doing any work with hardware (apart from working with SDKs that would control switches).

If you are like me and this is completely new and foreign territory to you, start with the tutorials located here.

In setting everything up, I had some initial problems with using the WiFi connect and instead opted for a wired LAN connection so I could rule this out as a possible error.

I am currently running Visual Studio 2017, and even with the latest version, I still had to download the latest IoT Core Project Templates.  Not a crazy extra step, but one you might want to do in advance of running through all the tutorials.


I skipped over the “Getting Started” app as I did not have the correct version of Windows 10 Creator running that created some issues when running the app in Visual Studio.  From a hardware perspective, I was able to get my light to blink, but not on my screen.

From here I played around with the Basic Blinking App and the Internet Radio app which was pretty cool to control from my phone and/or desktop concurrently.

Not much code to show and I debated whether I should blog about something at all, but sometimes it’s not about the oh so magical discovery and instead more about the journey… and that cool blinking light.


The Simplest Connection to Dynamics365

Whenever starting something new, you always want to find the quickest way to make something happen.

Think Hello World – I want Hello World (but not really Hello World) so I can start doing all that cool stuff.

I was searching the other day for some code on how to make an initial connection to Dynamics365 for the start of a new project.

Here were the objectives;

  1. I didn’t want to download someone else’s library on creating a connection.
  2. I wanted to learn how to connect to Dynamics365.

The first point is really important because although there are some really, really great libraries out there, it prevents the accomplishment of my second objective which was – I wanted to write the code, not consume someone else’s code.

The best way to learn how something really works is always to do it yourself.

So here it is, in all it’s unrefined, unchecked, (definitely not hardened and validated across multiple scenarios) glory, the simplest code to connect to Dynamics365.  All you need is to download the Dynamics365 SDK and add a reference Microsoft.Xrm.Sdk.

ClientCredentials credentials = new ClientCredentials();
 credentials.UserName.UserName = user;
 credentials.UserName.Password = password;

 string ServerUri = String.Format("{0}://{1}/XRMServices/2011/Organization.svc", protocol, Server);
 Uri serviceUri = new Uri(ServerUri);

OrganizationServiceProxy proxy = new OrganizationServiceProxy(serviceUri, null, credentials, null);
 IOrganizationService _CrmService = (IOrganizationService)proxy;
 catch (Exception ex)

And now we harden it, make it better and stronger.

Setting up Dynamics365 for the First Time

I recently went down the path of purchasing a Microsoft Action Pack so immediately went to setting it up in my pre-existing Office365 Tenant and ran into a few gotchas that might save you some time.

Office365 Business Essentials and Enterprise Plan 1 Licensing

I currently have an Office365 Business Essentials plan but when creating my Dynamics tenant quick realized that my users that were licensed under my Business Essentials license cannot be readily imported into Dynamics365 due to SharePoint plan conflicts.

There is a path to upgrade users through the Office365 Admin, but that’s for another blog.

Setting up Dynamics365

When creating your tenant for Dynamics, it’s not solely about your licenses, but also about creating the actual tenant.  To do this, you need to first navigate down to the Settings section of your Office365 Admin and select “Services & Add-Ins”.  From there you will be presented with the window below where you now create your new tenant simply by clicking “Manager your Dynamics 365 settings”.


From there you will be prompted to go through the same steps that you generally go through when deploying a tenant (perhaps with a different User Interface).


In the above screenshot, I have configured my first tenant to be a Sandbox where I can do my development and mess around with things.  Sandboxes were always there before but are now included with every plan, irrespective of your plan, granting you one free sandbox per client.


As you can see in the above screenshot, my tenant is now listed as a Sandbox and not Production.

Now we can get to doing some coding.