Don’t use your Methodology as a Band-Aid

I can’t remember a time when software development methodology was not a hot, contentious topic of discussion.

“We need to be Agile, because that will make us go faster”

“Scrum will save us from everything we are doing wrong”

“Waterfall is the devil’s child”

“Design Patterns are the only way to go”

“Design Patterns don’t work for me”

The problem with every architecture style and delivery methodology (new and old) is the same as it was yesterday, last year, five years ago and most likely in the 80s.

We refuse to look at what the problem is that we are trying to solve and instead are content with slapping a band-aid on it and calling it “fixed, because we now have #INSERT FAVOURITE METHODOLOGY HERE#”.

If you are not will to identify what is wrong with your delivery of software in the first place, you will never be able to apply the correct methodology that applies to you.

And when I say “identify what is wrong with your delivery of software”, saying “we’re always late” is a cop-out to the true problem.

My company BetaRover Inc, specializes in working with organizations getting over these humps and breaking through the Invisible Barriers that are holding them back.

Check us out, we’re always happy to chat.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Dynamics Workflow Registration Mismatch

Recently I was deploying an update to a workflow when I received the following message.

workflowfail

Upon further investigation, the cause of the problem were the dll references I was using for deploying this particular code to this particular environment.

I had updated my Dynamics SDK to use the latest set of dlls (8.2.0.566) while the environment I had already deployed to was on (7.1.0001.3108).  A few updated file references later and I was back in business – coding, registering, deploying and testing my code.

Don’t Sweat the Customizations

Dynamics365 (and it’s previous incarnations) is designed and built to be customized and integrated into your pre-existing Line of Business applications and/or seamlessly integrate into your new ones.

That’s the goal of the platform (in my humble opinion).

To this extent, the only times you should be afraid of performing customizations on the core or extended system are;

  • You don’t understand the requirements and are changing things willy, nilly all over the place.
  • You have gone beyond writing your own code and are now changing underlying code which may or may not be supported in future upgrades.
  • You are recreating functionality that already exists in the system in your own variant.
  • You are taking something called an account and making it look like a “cat” but then having to create another thing called an “account” because you messed up the initial account.

Those are times when customizations in Dynamics can get you into a world of hurt.

Now, think about your work as a C# developer, Java, Web, VB.NET, Python, PHP, whatever and read those 4 items again.

Notice anything?

…..

That’s right, those 4 tenets apply to any software development language or platform not ONLY Dynamics365.

I think the “problem” (if you want to call it a problem with Dynamics) is that Customization and Solution Architecture is a very easy to get up and running with (good) but you can miss a lot if you don’t know what you are doing (bad).  At the end of the day, don’t be afraid to customize and leverage core attributes, do be afraid when you are not leveraging functionality in the system and having to create your own.

It’s not good for you or your customers.

 

Why do I need the Unified Service Desk?

I’ve been (and will continue to do) some blogging on the Dynamics Unified Service Desk (USD) but I’ve failed to answer the first, probably most important question you might be asking yourself right now.

Why do I need the Unified Service Desk?

Before I proceed, answer these questions (no rush, I’ll wait).

  • Do I run a Contact Centre? Y/N
  • Do I have a phone system? Y/N
  • Do I already have Dynamics installed?  Y/N
  • Have I invested some serious $$$ in our company’s own proprietary Line of Business Applications? Y/N
  • Do I have agents that work remotely? Y/N

Do I run a Contact Centre?

Great, the USD is designed, from the ground up, to be your agent’s only app they will ever need to do their job.  No more wasted context switching between applications, no more trying to find the right app that applies to the right situation – it’s all there for them to use and consume when they need it.

Do I have a phone system?

Great, with the USD you can use (or purchase from a partner) the CTI – Computer Telephony Integration – SDK that enables you to work magic with incoming phone calls to your agent’s – i.e., ScreenPops.  With this SDK, you can enable the USD to listen onto telephony events that can open up Dynamics, search through it and determine next course of action without the agent having ever picked up the phone.

Do I already have Dynamics installed?

If yes, fantastic, the USD is free, the SDKs are free and all of those wonderful Dynamics customizations and forms you have in place are freely available in the USD.  You don’t need to create any new screens (unless you want to) or develop any new workflows (unless you want to) – you can leverage everything you have to be up and running today.

Have I invested some serious $$$ in our company’s own proprietary Line of Business Applications?

Great, the USD can host many Windows and Web-based applications as hosted controls.  If you want to get really fancy, you can enable Single Sign-On protocols to automatically sign in your agents to these other systems without forcing them to remember multiple credentials.

Do I have agents that work remotely?

Yes?  Great, they can download the USD to their desktop from wherever they are, login and begin working as if they were in the office.  It’s as simple as running an install.

I zipped through these questions pretty fast and so should you.  At the end of the day, the USD can help you deploy and deliver a unified Contact Centre experience to your customers and agents while reducing costs, leveraging your existing Dynamics 365 investments and not having to throw out years of investment in your existing Line of Business applications.

Best of all, the USD does not care if you are on-premise or in the cloud, it loves them all.

 

Adding Items to a Dynamics Queue

Continuing off my post of adding items to a queue programmatically, I wanted to add items to this queue (why else would I be using a queue?).

The code here is relatively simple and boring as I queried for a contact named Andrew, found him and added a new queueitem to the queue.

QueryExpression queryContact = new QueryExpression();
queryContact.EntityName = "contact";
queryContact.ColumnSet = new ColumnSet(true);
queryContact.Criteria.AddCondition("firstname", ConditionOperator.Equal, "Andrew");

EntityCollection entityContacts = _CrmService.RetrieveMultiple(queryContact);
EntityReference contactRef = new EntityReference("contact", entityContacts[0].Id);

Entity q = new Entity("queueitem");
q["queueid"] = new EntityReference("queue", _QueueId);
q["objectid"] = contactRef;
_CrmService.Create(q);

The results were anything but.

The first time I executed this code it worked fine, created a new queueitem record and associated to my man Andrew.

The second time I executed this code, it exploded with the following message (which seems odd for a queue to do).

Picture (Device Independent Bitmap) 1

So then I went to the contact record itself, tried to do this manually, but this time I received no error.  When I checked the queue though, it only had one instance of my queueitem in there.

Still perplexed, I then created a phone call activity, added my contact to it, then added that to the queue (multiple times) and this worked fine (and showed multiple instances in the queue).

Perhaps there is a difference between how Dynamics handles core entity interactions vs activities.  I find it odd that this restriction exists because every record goes into the queue as a unique queue item.  For what I was trying to achieve (logging changes to records, not activities, in the order they were processed) this was not going to work.

Unfortunately, I haven’t found a way around this functionality to disable it.  If anyone knows the reason, I would love to hear the why behind it.

 

Creating a USD Configuration

When getting started with development in the USD (Unified Service Desk), the first thing you have to do is create a configuration profile (otherwise you get an error when you launch the USD).

A configuration profile is what allows you to create many types of USD implementations and associate them to users.  A user can only ever be associated to one profile.

USD_Config

Establishing a base configuration profile is comprised of three parts as indicated below.

usd

The Global Manager is a hosted control which is core of any USD implementation.  The role of this control is load and host all controls related to your configuration, interpreting all controls, rules, toolbar components, scripts and sessions.  A single configuration can only contain one instance of the Global Manager hosted control.

The Connection Manager hosted control type manages connections to the Dynamics365 server, and makes it available to the rest of the agent application.  Theoretically, it would be possible to host an instance of the USD without a Connection Manager, but there would not be significant value to this approach (since it can’t read/write any data to/from Dynamics).

The Panel Layout hosted control defines the arrangement of panels in the Unified Service Desk. Panels can host various controls, and defines the arrangement of various hosted controls of the USD.  There are a number of predefined panel types to support various layout options such as tabbed layout, deck, and stacked layout.  If a Panel Layout type of hosted control is not defined in the application, the default panel layout, Standard Main Panel, is created automatically.

When you have created these three components and associated them to your USD Configuration, you should have a view akin to the following.

USD_Config_2

Best Practices: If I am implementing a custom USD configuration, whether it’s one configuration or many, I will always prepend all related components with a little descriptor (think CRM Publisher) so that I know what belongs to what when I’m associating components.

 

Accessing Dynamics Queues Programmatically

I typically still code in Dynamics using LateBound requests.  There have been a few instances where I have switched to Early Bound but I continue to do this for the following reasons

  1. I don’t like dragging around proxies into my code that can change environment to environment.
  2. When not depending on proxies, I feel have more options to downgrade my code into different versions based on what can be discovered.
  3. I get to learn about all the hidden relationships between entities and attributes that gives me a deeper understanding of what lies beneath.

With that said, this week I needed to access some queues in Dynamics and see what was in them.

To do this, I queried Dynamics for my queue based on the name provided.

QueryExpression query = new QueryExpression();
query.EntityName = "queue";
query.ColumnSet = new ColumnSet(true);
query.Criteria.AddCondition("name", ConditionOperator.Equal, "MySuperQueue");

EntityCollection entityResults = _CrmService.RetrieveMultiple(query);

From here, I was then able to query the queue for what it contains.

if (entityResults.Entities.Count == 1)
{
_CrmQueue = entityResults[0];

_QueueId = new Guid(_CrmQueue["queueid"].ToString());

QueryExpression queryQueues = new QueryExpression();
queryQueues.EntityName = "queueitem";
queryQueues.ColumnSet = new ColumnSet(true);
queryQueues.Criteria.AddCondition("queueid", ConditionOperator.Equal, _QueueId);

EntityCollection entityQueues = _CrmService.RetrieveMultiple(queryQueues);

foreach (Entity ent in entityQueues.Entities)
{
System.Diagnostics.Debug.WriteLine(ent["title"].ToString());
System.Diagnostics.Debug.WriteLine("ENTERED ON: " + ent["enteredon"].ToString());
if (ent.Contains("workeridmodifiedon"))
{
System.Diagnostics.Debug.WriteLine("BEING WORKED ON: " + ent["workeridmodifiedon"].ToString());
}

}
}

I’ll write another post on how to add an item to a queue, because that prevented some logic and general understanding of queues headaches that through me for a loop.

The key fields I want to highlight here are enteredon and workeridmodifiedon (both returning datetime values.  If you are managing a queue, enteredon is the datetime that the item was added to the queue and workeridmodifiedon is the much more important value that shows when the item as picked to be worked on.

A sad fact about Dynamic/CRM queues – all those fancy actions of Pick/Remove/Release – do not change the state of the queueitem in Dynamics which can present for some interesting challenges (a topic for another post).  I have to believe that interfacing with queues would be that much more robust if the status reasons changed as a result.

For now, now you know how to access the items in your queue from your own code.